Vérifiez si une variable est une chaîne en JavaScript


1744

Comment puis-je déterminer si une variable est une chaîne ou autre chose en JavaScript?

Réponses:


1692

Vous pouvez utiliser l' typeofopérateur:

var booleanValue = true; 
var numericalValue = 354;
var stringValue = "This is a String";
var stringObject = new String( "This is a String Object" );
alert(typeof booleanValue) // displays "boolean"
alert(typeof numericalValue) // displays "number"
alert(typeof stringValue) // displays "string"
alert(typeof stringObject) // displays "object"

Exemple de cette page Web . (Cependant, l'exemple a été légèrement modifié).

Cela ne fonctionnera pas comme prévu dans le cas de chaînes créées avec new String(), mais cela est rarement utilisé et recommandé contre [1] [2] . Consultez les autres réponses pour savoir comment les gérer, si vous le souhaitez.


  1. Le guide de style JavaScript de Google indique de ne jamais utiliser de wrappers d'objets primitifs .
  2. Douglas Crockford a recommandé que les wrappers d'objets primitifs soient déconseillés .

45
@ Wolfy87 Veuillez noter que dans certains cas, typeof stringValue peut renvoyer "objet" au lieu de "chaîne". Voir les commentaires sur ma réponse.
DRAX

163
Ma réponse préférée. L'argument contre cela est qu'il «échoue» pour les chaînes enveloppées comme new String('foo'), mais cela n'a pas d'importance parce que les chaînes enveloppées sont une fonctionnalité sans valeur que vous ne devriez pas utiliser. Le guide de style de Google les interdit , Douglas Crockford les veut obsolètes et aucune bibliothèque ne les utilise. Imaginez qu'ils n'existent pas et utilisez-les typeofsans crainte.
Mark Amery


2
@DanielLe, parce qu'il a proposé un remplacement qui résout certains problèmes, et non parce qu'il est contre en principe.
Vsevolod Golovanov

4
Si cela vous cause des maux de tête, 99,99% du temps, c'est parce que vous n'avez pas correctement structuré votre code. Ce n'est pas la faute de NaN d'exister et de faire ce qu'il fait, c'est quelque chose que vous devez prendre en compte, apprendre et garder à l'esprit la prochaine fois que vous travaillez avec du code qui pourrait le produire.
Mike 'Pomax' Kamermans

1911

C'est ce qui fonctionne pour moi:

if (typeof myVar === 'string' || myVar instanceof String)
// it's a string
else
// it's something else

77
Est-ce que "myVar instanceof String" fait quelque chose au-delà de "typeof myVar == 'string'"?
2012 à 13h59

81
@svth dont je me souvenais. En JavaScript, vous pouvez avoir un type de chaîne variable ou un type d'objet qui est une classe de chaîne (même chose - les deux sont des chaînes - mais définies différemment), c'est pourquoi il est vérifié deux fois.
DRAX

38
var somevar = new String ('somestring') console.log (typeof somevar) // object
Danubian Sailor

82
-1 parce que la instanceofvérification ici est un bruit inutile à moins que vous ne suiviez des pratiques de codage très inhabituelles , et cette réponse ne fait rien pour expliquer ce qu'elle fait ou pourquoi vous pourriez l'utiliser. La seule raison pour laquelle vous en auriez besoin est si vous utilisez des chaînes enveloppées d'objet, mais les chaînes enveloppées d'objet sont une fonctionnalité sans valeur que personne n'utilise et Google et Crockford condamnent tous les deux comme une mauvaise pratique ( google-styleguide.googlecode.com/svn/ trunk /… , crockford.com/javascript/recommend.html ).
Mark Amery

79
Je suis profondément en désaccord avec l'idée que l'écriture d'un code solide qui gère correctement les cas improbables est quelque chose à éviter. Vérifier les deux typeofet instanceofse sent comme un bon conseil si votre code peut être appelé par d'autres. @ Le postmessagecas de bord de MarkAmery est important si vous demandez "qu'est-ce que j'étais juste postmessaged?" - mais vous vous attendez à ce que cela soit géré à l'interface et non autorisé à se propager. Ailleurs, il semble correct de gérer des méthodes de codage non obsolètes même si certains esthètes JS les désapprouvent. Ne commentez JAMAIS votre code comme acceptant String, à moins qu'il ne le fasse vraiment!
Dewi Morgan

157

Étant donné que 580+ personnes ont voté pour une réponse incorrecte et 800+ ont voté pour une réponse qui fonctionne, mais comme un fusil de chasse, j'ai pensé qu'il pourrait être utile de refaire ma réponse sous une forme plus simple que tout le monde peut comprendre.

function isString(x) {
  return Object.prototype.toString.call(x) === "[object String]"
}

Ou, en ligne (j'ai une configuration UltiSnip pour cela):

Object.prototype.toString.call(myVar) === "[object String]"

Pour votre information, la réponse de Pablo Santa Cruz est faux, parce que typeof new String("string")estobject

La réponse de DRAX est précise et fonctionnelle, et devrait être la bonne réponse (puisque Pablo Santa Cruz est définitivement incorrect, et je ne contesterai pas le vote populaire.)

Cependant, cette réponse est également certainement correcte, et en fait la meilleure réponse (sauf, peut-être, pour la suggestion d'utiliser lodash / underscore ). mentions légales: J'ai contribué à la base de code lodash 4.

Ma réponse originale (qui a évidemment survolé de nombreuses têtes) suit:

J'ai transcodé ceci à partir de underscore.js:

['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'].forEach( 
    function(name) { 
        window['is' + name] = function(obj) {
              return toString.call(obj) == '[object ' + name + ']';
    }; 
});

Cela définira isString, isNumber, etc.


Dans Node.js, cela peut être implémenté en tant que module:

module.exports = [
  'Arguments',
  'Function', 
  'String', 
  'Number', 
  'Date', 
  'RegExp'
].reduce( (obj, name) => {
  obj[ 'is' + name ] = x => toString.call(x) == '[object ' + name + ']';
  return obj;
}, {});

[edit]: Object.prototype.toString.call(x)fonctionne pour délimiter également les fonctions et les fonctions asynchrones:

const fn1 = () => new Promise((resolve, reject) => setTimeout(() => resolve({}), 1000))
const fn2 = async () => ({})

console.log('fn1', Object.prototype.toString.call(fn1))
console.log('fn2', Object.prototype.toString.call(fn2))


11
Vous recommandez underscore.js (pour quelle raison étrange?) Mais vous ne l'utilisez pas ici. De plus, vous polluez l'espace de noms global avec des fonctions. Dans node.js, vous créeriez un module qui aurait toutes ces fonctions (vous pouvez utiliser à la global || windowplace de windowmais ce serait une mauvaise approche pour résoudre un problème que vous ne devriez pas avoir en premier lieu).
Benjamin Gruenbaum

19
@BenjaminGruenbaum Je suis venu chercher la réponse à la question du PO et je n'ai aimé aucune des réponses. J'ai donc vérifié ce que le trait de soulignement a fait, et j'ai pensé que c'était assez astucieux pour extraire et modifier un peu (pour éviter d'avoir à charger la bibliothèque de soulignement). Je vais clarifier mon message.
Orwellophile

2
@Orwellophile Cool, je comprends maintenant, votre réponse originale était formulée comme si vous proposiez de souligner elle-même. Personnellement, je vérifierais simplement myObject+"" === myObjectsi un objet est une chaîne (ou mieux encore, je ne taperais pas check dans un système de type basé sur le comportement en premier lieu).
Benjamin Gruenbaum

18
@Orwellophile, en quoi est-ce mieux que la réponse de DRAX?
Pacerier

3
JS prend en charge la correction de singe, il est donc possible de redéfinir le toStringdans le Object.prototype. Donc, je dirais que s'appuyer sur toStringpour vérifier le type d'un objet est, au mieux, une mauvaise pratique.
Andre Rodrigues

84

Je recommande d'utiliser les fonctions intégrées de jQuery ou lodash / Underscore . Ils sont plus simples à utiliser et plus lisibles.

L'une ou l'autre fonction gérera le cas mentionné par DRAX ... c'est-à-dire qu'ils vérifient tous les deux si (A) la variable est un littéral de chaîne ou (B) c'est une instance de l'objet String. Dans les deux cas, ces fonctions identifient correctement la valeur comme étant une chaîne.

lodash / Underscore.js

if(_.isString(myVar))
   //it's a string
else
   //it's something else

jQuery

if($.type(myVar) === "string")
   //it's a string
else
   //it's something else

Voir la documentation lodash pour _.isString () pour plus de détails.

Voir la documentation jQuery pour $ .type () pour plus de détails.


97
C'est l'essentiel de ce qui ne va pas avec la communauté JS - la vérification par rapport au type primitif est une ligne unique et implique uniquement la construction de la langue (l'une des bases), mais vous recommandez d'utiliser une bibliothèque externe. Si quelqu'un utilise déjà l'une de ces bibliothèques, ce pourrait être une bonne idée, mais les télécharger juste pour cela au lieu de simplement vérifier le type est une exagération.
Rafał Wrzeszcz

5
Je suis d'accord avec Rafal. Je constate partout que cela améliore la "lisibilité" de l'utilisation de l'une de ces bibliothèques externes. Si vous connaissez JavaScript, c'est plus facile à lire que certaines bibliothèques externes que vous n'avez pas utilisées. _.every()est un peu déroutant à utiliser au début, et quelque chose d'aussi simple que les développeurs _.isBoolean()confus dans mon entreprise. Un développeur a pensé à tort que ce serait faux si la valeur était un booléen et était fausse. L'anglais est plus facile à lire que l'allemand pour moi, car je ne connais pas l'allemand. Apprenez JavaScript et tout cela aura du sens.
John Harding

20
@ RafałWrzeszcz Ces bibliothèques sont assez largement utilisées et fournissent des fonctionnalités très utiles (et testées). Surtout lodash. Je ne recommanderais pas à quelqu'un de télécharger la bibliothèque uniquement pour l'utiliser pour cette seule solution .... mais je recommanderais à tous les développeurs javascript de télécharger cette bibliothèque et de voir ce qu'ils manquent. ;)
ClearCloud8

13
Il vous manque à tous l'intérêt d'une bibliothèque comme Lodash: pas la vitesse. Pas "facilité de développement". La raison d'utiliser une bibliothèque comme Lodash offre une "défense" contre les problèmes qui feront exploser votre application js. Des erreurs fatales se produisent lorsque vous tentez d'effectuer des opérations de chaîne sur un objet (ou vice versa), et Lodash fournit une valeur considérable pour éviter ces erreurs.
random_user_name

1
Gardez à l'esprit que beaucoup de gens le feront dans un environnement Node ou similaire à un Node, et très peu de gens utiliseront jQuery là-bas.
Matt Fletcher

35
function isString (obj) {
  return (Object.prototype.toString.call(obj) === '[object String]');
}

Je l'ai vu ici:

http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/


4
Je pense que cette solution est la plus robuste car elle gère les scénarios de référence cross-frame / cross-window comme mentionné dans l'URL fournie dans la réponse.
ewh

1
Excellente réponse, il semble que Underscore.js utilise également cette méthode!
Daan

1
@ling Juste curieux, pourquoi mettez-vous des parenthèses Object.prototype.toString.call(obj) === '[object String]'?
StubbornShowaGuy

@Earlee Vous voulez dire (x === y)que sa lisibilité est meilleure x === y?
StubbornShowaGuy

@StubbornShowaGuy À mon avis, oui. C'est aussi une question de cohérence. Personnellement, j'utilise toujours des parenthèses lors du retour d'une valeur.
Aquarelle

28

Meilleur moyen:

var s = 'String';
var a = [1,2,3];
var o = {key: 'val'};

(s.constructor === String) && console.log('its a string');
(a.constructor === Array) && console.log('its an array');
(o.constructor === Object) && console.log('its an object');
(o.constructor === Number || s.constructor === Boolean) && console.log('this won\'t run');

Chacun d'eux a été construit par sa fonction de classe appropriée, comme "new Object ()" etc.

En outre, Duck-Typing: "S'il ressemble à un canard, marche comme un canard et sent comme un canard - ce doit être un tableau". Signification, vérifiez ses propriétés.

J'espère que cela t'aides.

Éditer; 12/05/2016

N'oubliez pas que vous pouvez également toujours utiliser des combinaisons d'approches. Voici un exemple d'utilisation d'une carte d'actions en ligne avec typeof :

var type = { 'number': Math.sqrt.bind(Math), ... }[ typeof datum ];

Voici un exemple plus «réel» d'utilisation de cartes en ligne:

function is(datum) {
    var isnt = !{ null: true, undefined: true, '': true, false: false, 0: false }[ datum ];
    return !isnt;
}
console.log( is(0), is(false), is(undefined), ... );  // >> true true false

Cette fonction utiliserait le "type-casting" [personnalisé] - plutôt "type - / - value-mapping" - pour déterminer si une variable "existe" réellement. Maintenant, vous pouvez diviser ces cheveux désagréables entre null& 0!

Plusieurs fois, vous ne vous souciez même pas de son type . Une autre façon de contourner la frappe consiste à combiner des ensembles de type canard:

this.id = "998";  // use a number or a string-equivalent
function get(id) {
    if (!id || !id.toString) return;
    if (id.toString() === this.id.toString()) http( id || +this.id );
    // if (+id === +this.id) ...;
}

Les deux Number.prototype et String.prototype ont un .toString() method. Vous venez de vous assurer que l'équivalent chaîne du nombre était le même, puis vous vous êtes assuré que vous l'avez passé dans la httpfonction en tant que Number. En d' autres termes, on n'a même pas soin ce que son type était.

J'espère que cela vous donne plus de travail :)


Vous auriez besoin d'une autre vérification pour les anciens numéros simples, car essayer de prendre leur propriété constructeur échouera:

@torazaburo a bien fonctionné pour moi tout à l'heure dans la console Chrome. Qu'est-ce qui vous fait penser que cela ne fonctionnera pas?
Mark Amery

2
@torazaburo Vous voudrez peut-être jouer avec les assertions ( (o.constructor === Number || s.constructor === Boolean)). Anecdotique, parseIntet NaNsont des outils fragiles mais puissants. N'oubliez pas que Not-a-Number n'est PAS Not-a-Number et qu'undefined peut être défini.
Cody

1
a.constructor === Array est incorrect et peut parfois échouer, utilisez Array.isArray voir web.mit.edu/jwalden/www/isArray.html
axkibe

1
D'accord, ce n'est pas sûr. Une meilleure façon consiste à utiliser les vérifications de propriété - C'EST le seul moyen vraiment sûr à l'heure actuelle. Exemple: if(thing.call) { 'its a function'; }ou if(thing.defineProperties) { 'its an object'; }. Merci pour la contribution, axkibe!
Cody

17

Honnêtement, je ne vois pas pourquoi on n'utiliserait pas simplement typeofdans ce cas:

if (typeof str === 'string') {
  return 42;
}

Oui, il échouera contre les chaînes enveloppées d'objets (par exemple new String('foo')), mais celles-ci sont largement considérées comme une mauvaise pratique et la plupart des outils de développement modernes sont susceptibles de décourager leur utilisation. (Si vous en voyez un, réparez-le!)

L' Object.prototype.toStringastuce est quelque chose que tous les développeurs frontaux ont été reconnus coupables d'avoir fait un jour dans leur carrière, mais ne vous laissez pas tromper par son raffinement intelligent: il se cassera dès que quelque chose de singulier corrigera le prototype Object:

const isString = thing => Object.prototype.toString.call(thing) === '[object String]';

console.log(isString('foo'));

Object.prototype.toString = () => 42;

console.log(isString('foo'));


15

J'aime utiliser cette solution simple:

var myString = "test";
if(myString.constructor === String)
{
     //It's a string
}

3
En quoi est-ce différent de la réponse de Cody, 4 ans plus tard?
Jonathan H

3
La réponse de @Sheljohn Cody est excellente. Ma réponse (texte complet) est plus courte et directe. Vous avez demandé ... :)
ScottyG

En tant que fonction, cela aurait besoin d'un moyen de traiter avec undefinedet null, et de toujours obtenir la bonne réponse pour les chaînes vides (les deux ''et new String('')).
MikeBeaton

@MikeBeaton Pas de problème: (mystring || false) && mystring.constructor === String. J'ai utilisé false au cas où il serait utilisé dans une fonction qui doit renvoyer un booléen.
alans

13

Ceci est un excellent exemple de l'importance des performances:

Faire quelque chose d'aussi simple qu'un test pour une chaîne peut être coûteux s'il n'est pas fait correctement.

Par exemple, si je voulais écrire une fonction pour tester si quelque chose est une chaîne, je pourrais le faire de deux manières:

1) const isString = str => (Object.prototype.toString.call(str) === '[object String]');

2) const isString = str => ((typeof str === 'string') || (str instanceof String));

Ces deux éléments sont assez simples, alors qu'est-ce qui pourrait avoir un impact sur les performances? De manière générale, les appels de fonction peuvent être coûteux, surtout si vous ne savez pas ce qui se passe à l'intérieur. Dans le premier exemple, il existe un appel de fonction à la méthode toString d'Object. Dans le deuxième exemple, il n'y a pas d'appels de fonction, car typeof et instanceof sont des opérateurs. Les opérateurs sont beaucoup plus rapides que les appels de fonction.

Lorsque les performances sont testées, l'exemple 1 est 79% plus lent que l'exemple 2!

Voir les tests: https://jsperf.com/isstringtype


Le lien de test est mort, mais je vous crois. Ce genre d'information est super important. À mon humble avis, cela devrait être, sinon la réponse la plus positive, au moins le commentaire le plus positif sur la réponse principale actuelle.
Coderer du

typeof str === 'string' || str instanceof String(peut laisser tomber la parenthèse que je préfère dans les if (..)cas); indépendamment, la vérification à la fois des types primitifs et des objets dans # 2 est claire et suffisante. Ces vérifications devraient de toute façon être «rares».
user2864740

13
if (s && typeof s.valueOf() === "string") {
  // s is a string
}

Fonctionne pour les littéraux de chaîne let s = 'blah'et pour les chaînes d'objetslet s = new String('blah')


3
Attention! Cela échouera sur les chaînes vides, car ce sont des falsey.
Philipp Sumi

8

Extrait de lodash:

function isString(val) {
   return typeof val === 'string' || ((!!val && typeof val === 'object') && Object.prototype.toString.call(val) === '[object String]');
}

console.log(isString('hello world!')); // true
console.log(isString(new String('hello world'))); // true

Si quelqu'un veut connaître la source, c'est github.com/lodash/lodash/blob/master/isString.js
Ricardo Canelas

5

Je pense que la solution @customcommander devrait suffire dans 90% de vos cas:

typeof str === 'string'

Devrait vous servir correctement (simplement parce que normalement il n'y a aucune raison d'avoir new String('something')dans votre code).

Si vous souhaitez gérer le String objet (par exemple, vous vous attendez à une var d'un tiers), alors utiliser lodash comme @ ClearCloud8 suggéré semble être une solution claire, simple et élégante.

Je suggérerais cependant d'être prudent avec les bibliothèques telles que lodash en raison de leur taille. Au lieu de faire

import _ from 'lodash'
...
_.isString(myVar)

Ce qui apporte tout l'énorme objet lodash, je suggère quelque chose comme:

import { isString as _isString } from 'lodash'
...
_isString(myVar)

Et avec un regroupement simple, ça devrait aller (je me réfère ici au code client).


pourquoi === quand == est suffisant
zavr

4

Si vous travaillez sur l'environnement node.js, vous pouvez simplement utiliser la fonction intégrée isString dans les utilitaires.

const util = require('util');
if (util.isString(myVar)) {}

Edit: comme @Jehy l'a mentionné, cela est obsolète depuis la v4.


Y a-t-il un remplacement?
Anthony Kong

3
Les documents disent "Utiliser à la typeof value === 'string'place".
M. Rogers

x = new String('x'); x.isString(x);renvoie faux . Il y a util.types.isStringObject()mais cela renvoie false pour le x = 'x'type chaîne. Deux fonctions utilitaires qui ne fournissent absolument aucune utilité ...
spinkus

4

La méthode suivante vérifie si une variable est une chaîne ( y compris les variables qui n'existent pas ).

const is_string = value => {
  try {
    return typeof value() === 'string';
  } catch (error) {
    return false;
  }
};

let example = 'Hello, world!';

console.log(is_string(() => example)); // true
console.log(is_string(() => variable_doesnt_exist)); // false

3

J'ai également trouvé que cela fonctionne bien aussi, et c'est beaucoup plus court que les autres exemples.

if (myVar === myVar + '') {
   //its string
} else {
   //its something else
}

En concaténant sur des guillemets vides, il transforme la valeur en chaîne. Si myVarest déjà une chaîne, l'instruction if réussit.


3
Le seul problème est que vous contraignez une variable lorsque vous voulez vérifier son type. Cela me semble un peu cher par rapport à typeof.
Olical

1
Alors oui, vous avez raison. jsperf a déclaré qu'il était environ 20% plus lent que typeofmais encore un peu plus rapide que toString. Quoi qu'il en soit, je suppose que j'aime juste la syntaxe de la contrainte.
Chris Dolphin

4
cela ne fonctionne pas avec le type String; var s = new String('abc'); > s === s + '' > false
user5672998

1
Ne fonctionne pas avec new Stringcus qui crée un type de object. w3schools.com/js/tryit.asp?filename=tryjs_string_object2
Chris Dolphin

Bonne pensée, mais laisse de côté le cas du bord des chaînes enveloppées d'objets.
Anthony Rutledge

3
var a = new String('')
var b = ''
var c = []

function isString(x) {
  return x !== null && x !== undefined && x.constructor === String
}

console.log(isString(a))
console.log(isString(b))
console.log(isString(c))

Pourquoi devez-vous vérifier la valeur null ou undefined si x.constructor === String renvoie également false pour null ou undefined?
Jules Manson

1
@JulesManson: Cela déclencherait une erreur, ne produirait pas false.
Ry-

3

Je trouve cette technique simple utile pour effectuer une vérification de type pour String -

String(x) === x // true, if x is a string
                // false in every other case

const test = x =>
  console.assert
    ( String(x) === x
    , `not a string: ${x}`
    )

test("some string")
test(123)           // assertion failed
test(0)             // assertion failed
test(/some regex/)  // assertion failed
test([ 5, 6 ])      // assertion failed
test({ a: 1 })      // assertion failed
test(x => x + 1)    // assertion failed

La même technique fonctionne aussi pour Number -

Number(x) === x // true, if x is a number
                // false in every other case

const test = x =>
  console.assert
    ( Number(x) === x
    , `not a number: ${x}`
    )

test("some string") // assertion failed
test(123)           
test(0)             
test(/some regex/)  // assertion failed
test([ 5, 6 ])      // assertion failed
test({ a: 1 })      // assertion failed
test(x => x + 1)    // assertion failed

Et pour RegExp -

RegExp(x) === x // true, if x is a regexp
                // false in every other case

const test = x =>
  console.assert
    ( RegExp(x) === x
    , `not a regexp: ${x}`
    )

test("some string") // assertion failed
test(123)           // assertion failed
test(0)             // assertion failed
test(/some regex/)  
test([ 5, 6 ])      // assertion failed
test({ a: 1 })      // assertion failed
test(x => x + 1)    // assertion failed

Idem pour l' objet -

Object(x) === x // true, if x is an object
                // false in every other case

NB, les regexps, les tableaux et les fonctions sont également considérés comme des objets.

const test = x =>
  console.assert
    ( Object(x) === x
    , `not an object: ${x}`
    )

test("some string") // assertion failed
test(123)           // assertion failed
test(0)             // assertion failed
test(/some regex/)  
test([ 5, 6 ])      
test({ a: 1 })      
test(x => x + 1)    

Mais, vérifier Array est un peu différent -

Array.isArray(x) === x // true, if x is an array
                       // false in every other case

const test = x =>
  console.assert
    ( Array.isArray(x)
    , `not an array: ${x}`
    )

test("some string") // assertion failed
test(123)           // assertion failed
test(0)             // assertion failed
test(/some regex/)  // assertion failed
test([ 5, 6 ])      
test({ a: 1 })      // assertion failed
test(x => x + 1)    // assertion failed

Cette technique ne fonctionne cependant pas pour les fonctions -

Function(x) === x // always false

var x = new String(x); String(x)===xrenvoie faux. mais ({}).toString.call(x).search(/String/)>0revient toujours pour les choses filandreuses
non synchronisé le

1
function isClass(x,re){return ({}).toString.call(x).search(re)>0;}; isClass("hello",/String/) ou isClass(3,/Number/)ouisClass(null,/Null/)
non synchronisé le

2

Une solution simple serait:

var x = "hello"

if(x === x.toString()){
// it's a string 
}else{
// it isn't
}

1
cela ne vérifie pas s'il s'agit d'une chaîne. Cela fait une chaîne, beaucoup de choses ont une toString()fonction
Muhammad Umer

7
@MuhammadUmer Oui, il la convertit en chaîne mais vérifie ensuite l'identité par rapport à la valeur d'origine, qui ne sera vraie que si la valeur d'origine est également une chaîne.
MrWhite

4
c'est faux: vous ne pouvez invoquer aveuglément .toStringaucune valeur; essayez si le x à vérifier est nul ou non défini, votre exception de
levée de

1
L'idée est toujours utilisable. x === String (x) est sûr et fonctionne.
Márton Sári

Vraiment? Cette solution me semble trop bizarre, car la toString()méthode peut être remplacée et peut lever une exception (en raison d'une implémentation spécifique), et votre vérification ne fonctionnera pas avec certitude. L'idée principale est que vous ne devez pas appeler des méthodes qui ne sont pas liées à ce que vous souhaitez obtenir. Je ne parle même pas de frais généraux inutiles liés à la toStringméthode. Downvoting.
Rustem Zinnatullin

2

Un assistant Typechecker:

function isFromType(variable, type){
  if (typeof type == 'string') res = (typeof variable == type.toLowerCase())
  else res = (variable.constructor == type)
  return res
}

usage:

isFromType('cs', 'string') //true
isFromType('cs', String) //true
isFromType(['cs'], Array) //true
isFromType(['cs'], 'object') //false

Aussi, si vous voulez qu'il soit récursif (comme Array qui est un objet), vous pouvez l'utiliser instanceof.

( ['cs'] instanceof Object //true)


2

Je vais suivre un chemin différent vers le reste ici, qui essaie de dire si une variable est un type spécifique, ou un membre d'un ensemble spécifique, de types.
JS est construit sur ducktyping; si quelque chose craque comme une chaîne, nous pouvons et devons l'utiliser comme une chaîne.

Est-ce 7une chaîne? Alors pourquoi ça /\d/.test(7)marche?
Est-ce {toString:()=>('hello there')}une chaîne? Alors pourquoi ça ({toString:()=>('hello there')}) + '\ngeneral kenobi!'marche?
Ce ne sont pas des questions sur doit - le travail ci - dessus, le point est qu'ils font.

J'ai donc fait une duckyString()fonction
ci-dessous, je teste de nombreux cas non pris en charge par d'autres réponses. Pour chacun le code:

  • définit une variable de type chaîne
  • exécute une opération de chaîne identique et une vraie chaîne pour comparer les sorties (prouvant qu'elles peuvent être traitées comme des chaînes)
  • convertit la chaîne en une chaîne réelle pour vous montrer duckyString()de normaliser les entrées pour le code qui attend de vraies chaînes
text = 'hello there';
out(text.replace(/e/g, 'E') + ' ' + 'hello there'.replace(/e/g, 'E'));
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');

text = new String('oh my');
out(text.toUpperCase() + ' ' + 'oh my'.toUpperCase());
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');

text = 368;
out((text + ' is a big number') + ' ' + ('368' + ' is a big number'));
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');

text = ['\uD83D', '\uDE07'];
out(text[1].charCodeAt(0) + ' ' + '😇'[1].charCodeAt(0));
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');

function Text() { this.math = 7; }; Text.prototype = {toString:function() { return this.math + 3 + ''; }}
text = new Text();
out(String.prototype.match.call(text, '0') + ' ' + text.toString().match('0'));
out('Is string? ' + duckyString(text) + '\t"' + duckyString(text, true) + '"\n');

C'est dans la même veine que !!xpar opposition à x===trueet tester si quelque chose ressemble à un tableau au lieu de nécessiter un tableau réel.
objets jQuery; sont-ils des tableaux? Non. Sont-ils assez bons? Oui, vous pouvez très bien les exécuter grâce à des Array.prototypefonctions.
C'est cette flexibilité qui donne à JS sa puissance, et le test des chaînes rend spécifiquement votre code moins interopérable.

La sortie de ce qui précède est:

hEllo thErE hEllo thErE
Is string? true "hello there"

OH MY OH MY
Is string? true "oh my"

368 is a big number 368 is a big number
Is string? true "368"

56839 56839
Is string? true "😇"

0 0
Is string? true "10"

Il s'agit donc de savoir pourquoi vous voulez savoir si quelque chose est une chaîne.
Si, comme moi, vous êtes arrivé ici de Google et que vous vouliez voir si quelque chose ressemblait à une chaîne , voici une réponse.
Ce n'est même pas cher, sauf si vous travaillez avec des tableaux de caractères très longs ou profondément imbriqués.
C'est parce que ce sont toutes des instructions if, aucune fonction ne s'appelle like .toString().
Sauf si vous essayez de voir si un tableau de caractères avec des objets qui n'ont que des caractères toString()'s ou multi-octets, auquel cas il n'y a pas d'autre moyen de vérifier que de créer la chaîne et de compter les caractères que les octets constituent respectivement

function duckyString(string, normalise, unacceptable) {
    var type = null;
    if (!unacceptable)
        unacceptable = {};
    if (string && !unacceptable.chars && unacceptable.to == null)
        unacceptable.to = string.toString == Array.prototype.toString;

    if (string == null)
        ;

    //tests if `string` just is a string
    else if (
        !unacceptable.is &&
        (typeof string == 'string' || string instanceof String)
    )
        type = 'is';

    //tests if `string + ''` or `/./.test(string)` is valid
    else if (
        !unacceptable.to &&
        string.toString && typeof string.toString == 'function' && string.toString != Object.prototype.toString
    )
        type = 'to';

    //tests if `[...string]` is valid
    else if (
        !unacceptable.chars &&
        (string.length > 0 || string.length == 0)
    ) {
        type = 'chars';
        //for each char
        for (var index = 0; type && index < string.length; ++index) {
            var char = string[index];

            //efficiently get its length
            var length = ((duckyString(char, false, {to:true})) ?
                char :
                duckyString(char, true) || {}
            ).length;

            if (length == 1)
                continue;

            //unicode surrogate-pair support
            char = duckyString(char, true);
            length = String.prototype[Symbol && Symbol.iterator];
            if (!(length = length && length.call(char)) || length.next().done || !length.next().done)
                type = null;
        }
    }

    //return true or false if they dont want to auto-convert to real string
    if (!(type && normalise))
        //return truthy or falsy with <type>/null if they want why it's true
        return (normalise == null) ? type != null : type;

    //perform conversion
    switch (type) {
    case 'is':
        return string;
    case 'to':
        return string.toString();
    case 'chars':
        return Array.from(string).join('');
    }
}

Sont incluses des options pour

  • demander quelle méthode l'a jugé string-y
  • exclure les méthodes de détection de chaîne (par exemple, si vous n'aimez pas .toString())

Voici plus de tests car je suis complétiste:

out('Edge-case testing')
function test(text, options) {
    var result = duckyString(text, false, options);
    text = duckyString(text, true, options);
    out(result + ' ' + ((result) ? '"' + text + '"' : text));
}
test('');
test(null);
test(undefined);
test(0);
test({length:0});
test({'0':'!', length:'1'});
test({});
test(window);
test(false);
test(['hi']);
test(['\uD83D\uDE07']);
test([['1'], 2, new String(3)]);
test([['1'], 2, new String(3)], {chars:true});
  • Tous les cas négatifs semblent être pris en compte
  • Cela devrait fonctionner sur les navigateurs> = IE8
  • Tableaux de caractères avec plusieurs octets pris en charge sur les navigateurs avec prise en charge de l'itérateur de chaîne

Production:

Edge-case testing
is ""
null null
null null
to "0"
chars ""
chars "!"
null null
chars ""
to "false"
null null
chars "😇"
chars "123"
to "1,2,3"

1

Juste pour développer la réponse de @ DRAX , je ferais ceci:

function isWhitespaceEmptyString(str)
{
    //RETURN:
    //      = 'true' if 'str' is empty string, null, undefined, or consists of white-spaces only
    return str ? !(/\S/.test(str)) : (str === "" || str === null || str === undefined);
}

Il prendra également en compte les nulls et les undefinedtypes, et il prendra en charge les types non-chaîne, tels que 0.


1

C'est assez bon pour moi.

AVERTISSEMENT: ce n'est pas une solution parfaite. Voir le bas de mon post.

Object.prototype.isString = function() { return false; };
String.prototype.isString = function() { return true; };

var isString = function(a) {
  return (a !== null) && (a !== undefined) && a.isString();
};

Et vous pouvez utiliser ceci comme ci-dessous.

//return false
isString(null);
isString(void 0);
isString(-123);
isString(0);
isString(true);
isString(false);
isString([]);
isString({});
isString(function() {});
isString(0/0);

//return true
isString("");
isString(new String("ABC"));

AVERTISSEMENT: cela ne fonctionne pas correctement dans le cas:

//this is not a string
var obj = {
    //but returns true lol
    isString: function(){ return true; }
}

isString(obj) //should be false, but true

-1

Vous pouvez utiliser cette fonction pour déterminer le type de n'importe quoi:

var type = function(obj) {
    return Object.prototype.toString.apply(obj).replace(/\[object (.+)\]/i, '$1').toLowerCase();
};

Pour vérifier si une variable est une chaîne:

type('my string') === 'string' //true
type(new String('my string')) === 'string' //true
type(`my string`) === 'string' //true
type(12345) === 'string' //false
type({}) === 'string' // false

https://codepen.io/patodiblasi/pen/NQXPwY?editors=0012


-2

Je ne sais pas si vous voulez savoir s'il s'agit d'un type stringquel que soit son contenu, ou si son contenu est un nombre ou une chaîne, quel que soit son type.

Donc, pour savoir si son type est une chaîne, cela a déjà été répondu.
Mais pour savoir en fonction de son contenu si c'est une chaîne ou un nombre, j'utiliserais ceci:

function isNumber(item) {
    return (parseInt(item) + '') === item;
}

Et pour quelques exemples:

isNumber(123);   //true
isNumber('123'); //true
isNumber('123a');//false
isNumber('');    //false

Je pense que je demandais à l'origine comment vérifier le type, même si je ne savais même pas comment formuler la question à l'époque. (et je le ferais probablement avec /^\d+$/.test('123')pour éviter les subtilités des problèmes potentiels d'analyse)
Olical
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.