web-dev-qa-db-fra.com

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

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

1341
Olical

Vous pouvez utiliser l'opérateur typeof:

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 tiré de cette page Web . (Exemple légèrement modifié cependant).

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


  1. Le Guide de style Google JavaScript indique de ne jamais utiliser les wrappers d’objets primitifs .
  2. Douglas Crockford a recommandé que les wrappers d’objets primitifs soient déconseillés .
1289
Pablo Santa Cruz

C'est ce qui fonctionne pour moi:

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

Étant donné que plus de 580 personnes ont voté pour une réponse incorrecte et plus de 800 ont voté pour une réponse qui fonctionne, mais de style fusil à pompe, j'ai pensé qu'il serait peut-être intéressant de refaire ma réponse sous une forme plus simple, compréhensible pour tout le monde.

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 fausse, car typeof new String("string") est object

La réponse de DRAX est exacte et fonctionnelle, et devrait être la bonne (puisque Pablo Santa Cruz est très certainement incorrect et que je ne vais pas contester le vote populaire).

Cependant, cette réponse est également tout à fait correcte et en fait la meilleure (sauf peut-être pour la suggestion d'utiliser lodash / underscore ). disclaimer: j'ai contribué à lodash 4 codebase.

Ma réponse initiale (qui a évidemment volé au-dessus de nombreuses têtes) est la suivante: 

J'ai transcodé ceci 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;
}, {});
113
Orwellophile

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

Chacune des fonctions gérera le cas mentionné par DRAX ... c’est-à-dire qu’elles les deux vérifient si (A) la variable est un littéral de chaîne ou (B) 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 Documentation jQuery pour $ .type () pour plus de détails.

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

J'ai vu ça ici:

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

31
ling

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 de ceux-ci a été construit par sa fonction de classe appropriée, comme "new Object ()" etc.

En outre, Duck-Typing: "Si cela ressemble à un canard, marche comme un canard et sent comme un canard - ce doit être un tableau" Sens. Vérifiez ses propriétés.

J'espère que cela t'aides.

Modifier; 12/05/2016

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

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

Voici un exemple plus réel d'utilisation d'inline-maps:

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 [custom] "typage" - plutôt "typage -/- value-mapping" - pour déterminer si une variable "existait réellement". Maintenant, vous pouvez séparer ces cheveux méchants entre null & 0!

Plusieurs fois vous ne vous souciez même pas de son type. Une autre façon de contourner la saisie 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) ...;
}

Number.prototypeetString.prototype ont une .toString() method. Vous venez de vous assurer que l'équivalent chaîne du nombre était identique, puis vous vous êtes assuré de le transmettre à la fonction http en tant que Number. En d'autres termes, nous ne nous sommes même pas souciés de son type.

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

18
Cody

J'aime utiliser cette solution simple:

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

Tiré 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
7
Benj Sicam

C’est un excellent exemple de l’importance de la performance:

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));

Les deux 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 de Object. Dans le deuxième exemple, il n'y a pas d'appel de fonction, car typeof et instanceof sont des opérateurs. Les opérateurs sont nettement plus rapides que les appels de fonction.

Lorsque la performance est testée, l'exemple 1 est 79% plus lent que l'exemple 2!

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

6
Rob Brander

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

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

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

5
David

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

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

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

5
Chris Dolphin
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))
3
Jake

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

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

Oui, il échouera avec les chaînes encapsulées dans un objet (par exemple, new String('foo')), mais celles-ci sont largement considérées comme une mauvaise pratique et les outils de développement les plus modernes risquent de décourager leur utilisation. (Si vous en voyez un, corrigez-le!)

Le truc Object.prototype.toString est quelque chose que tous les développeurs front-end ont été reconnu coupable de faire un jour de leur carrière, mais ne le laissez pas vous tromper par son astuce astucieuse: il va se casser dès que quelque chose touche 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'));

3
customcommander

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

typeof str === 'string'

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

Si vous souhaitez également manipuler l'objet String (par exemple, vous attendez du var d'un tiers), utiliser lodash comme suggéré par @ ClearCloud8 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 amène tout l’énorme objet lodash, je suggérerais quelque chose comme:

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

Et avec un simple regroupement, ça devrait aller (je parle ici de code client).

3
Erez Cohen

Une solution simple serait:

var x = "hello"

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

Je trouve cette technique simple utile pour vérifier le type 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 pour Number aussi -

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 Object -

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

NB, les expressions rationnelles, 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 pas pour Fonctions -

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

Juste pour développer @/DRAX répondre , 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 tiendra également compte des types nulls et undefined et se chargera des types non-chaîne, tels que 0.

0
ahmd0

Vous pouvez utiliser cette fonction pour déterminer le type de quoi que ce soit:

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

La méthode suivante vérifiera 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
0
Grant Miller

C'est assez bien pour moi.

ATTENTION: Ce n’est pas une solution parfaite .

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"));

ATTENTION: Ceci ne fonctionne pas correctement dans le cas suivant:

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

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