web-dev-qa-db-fra.com

variable === undefined vs typeof variable === "undefined"

Les directives jQuery Core Style suggèrent deux manières différentes de vérifier si une variable est définie.

  • Variables globales: typeof variable === "undefined"
  • Variables locales: variable === undefined
  • Propriétés: object.prop === undefined

Pourquoi jQuery utilise-t-il une approche pour les variables globales et une autre pour les variables locales et les propriétés?

249
Patrick McElhaney

Pour les variables non déclarées, typeof foo renverra le littéral chaîne "undefined", alors que le contrôle d'identité foo === undefined déclenchera l'erreur "foo n'est pas défini".

Pour les variables locales (que vous savez sont déclarées quelque part), aucune erreur de ce type ne se produirait, d'où le contrôle d'identité.

308
Linus Kleen

Je me contenterais d'utiliser typeof foo === "undefined" partout. Cela ne peut jamais aller mal.

J'imagine que la raison pour laquelle jQuery recommande les deux méthodes différentes est qu'elles définissent leur propre variable undefined au sein de la fonction dans laquelle réside le code jQuery. Par conséquent, la fonction undefined est à l'abri de toute falsification de l'extérieur. J'imagine aussi que quelqu'un, quelque part, a comparé les deux approches et découvert que foo === undefined est plus rapide et a donc décidé que c'était la voie à suivre. [UPDATE: comme indiqué dans les commentaires, la comparaison avec undefined est également un peu plus courte, ce qui pourrait être un facteur à prendre en compte.] Cependant, le gain dans les situations pratiques sera tout à fait insignifiant: cette vérification ne sera jamais, de quelque manière que ce soit goulot d’étranglement et ce que vous perdez est important: évaluer une propriété d’un objet hôte à des fins de comparaison peut générer une erreur, alors que la vérification typeof ne le fera jamais.

Par exemple, ce qui suit est utilisé dans IE pour analyser XML:

var x = new ActiveXObject("Microsoft.XMLDOM");

Pour vérifier si sa méthode loadXML est sécurisée:

typeof x.loadXML === "undefined"; // Returns false

D'autre part:

x.loadXML === undefined; // Throws an error

METTRE À JOUR

Un autre avantage du contrôle typeof que j’ai oublié de mentionner est qu’il fonctionne également avec des variables non déclarées, ce que le contrôle foo === undefined ne permet pas, et jette en fait un ReferenceError. Merci à @ LinusKleen de me l'avoir rappelé. Par exemple:

typeof someUndeclaredVariable; // "undefined"
someUndeclaredVariable === undefined; // throws a ReferenceError

En bout de ligne: utilisez toujours le contrôle typeof.

106
Tim Down

Une autre raison d'utiliser la variante typeof: undefined peut être redéfinie.

undefined = "foo";
var variable = "foo";
if (variable === undefined)
  console.log("eh, what?!");

Le résultat de typeof variable ne le peut pas.

Mise à jour : notez que ce n'est pas le cas dans ES5.

26
Jakob

Qui est intéressé par le gain de performance de variable === undefined, peut regarder ici, mais cela semble être une optimisation de chrome uniquement.

6
RiZKiT

Parce que undefined n'est pas toujours déclaré, mais jQuery déclare undefined dans sa fonction principale. Ils utilisent donc la valeur safe undefined en interne, mais à l'extérieur, ils utilisent le style typeof pour être sûr.

6
Struppi

Résumé:

Lorsque nous sommes au niveau global, nous voulons réellement renvoyer true si la variable n'est pas déclarée ou a la valeur undefined:

var globalVar1;

// This variable is declared, but not defined and thus has the value undefined
console.log(globalVar1 === undefined);

// This variable is not declared and thus will throw a referenceError
console.log(globalVar2 === undefined);

Parce que dans la portée globale, nous ne sommes pas sûrs à 100% si une variable est déclarée, cela pourrait nous donner une erreur referenceError. Lorsque nous utilisons l'opérateur typeof sur la variable inconnue, nous n'obtenons pas ce problème lorsque la variable n'est pas déclarée:

var globalVar1;

console.log(typeof globalVar1 === 'undefined');
console.log(typeof globalVar2 === 'undefined');

Cela est dû au fait que l'opérateur typeof renvoie la chaîne undefined lorsqu'une variable n'est pas déclarée ou qu'elle contient actuellement la valeur undefined, qui correspond exactement à ce que nous souhaitons.


  • Avec les variables locales, nous n'avons pas ce problème car nous savons d'avance que cette variable existera. Nous pouvons simplement regarder dans la fonction respective si la variable est présente.
  • Avec les propriétés d'objet, nous n'avons pas ce problème car lorsque nous essayons de rechercher une propriété d'objet qui n'existe pas, nous obtenons également la valeur undefined

var obj = {};

console.log(obj.myProp === undefined);

1

Pour les variables locales, la vérification avec localVar === undefined fonctionnera car elles doivent avoir été définies quelque part dans la portée locale ou elles ne seront pas considérées comme locales.

Pour les variables qui ne sont ni locales ni définies nulle part, la vérification someVar === undefined lèvera une exception: Uncaught ReferenceError: j n'est pas défini

Voici un code qui clarifiera ce que je dis ci-dessus. Veuillez prêter attention aux commentaires en ligne pour plus de clarté.

function f (x) {
    if (x === undefined) console.log('x is undefined [x === undefined].');
    else console.log('x is not undefined [x === undefined.]');

    if (typeof(x) === 'undefined') console.log('x is undefined [typeof(x) === \'undefined\'].');
    else console.log('x is not undefined [typeof(x) === \'undefined\'].');

    // This will throw exception because what the hell is j? It is nowhere to be found.
    try
    {
        if (j === undefined) console.log('j is undefined [j === undefined].');
        else console.log('j is not undefined [j === undefined].');
    }
    catch(e){console.log('Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.');}

    // However this will not throw exception
    if (typeof j === 'undefined') console.log('j is undefined (typeof(x) === \'undefined\'). We can use this check even though j is nowhere to be found in our source code and it will not throw.');
    else console.log('j is not undefined [typeof(x) === \'undefined\'].');
};

Si nous appelons le code ci-dessus comme ceci:

f();

La sortie serait la suivante:

x is undefined [x === undefined].
x is undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.

Si nous appelons le code ci-dessus comme ceci (avec n'importe quelle valeur en fait):

f(null); 
f(1);

La sortie sera:

x is not undefined [x === undefined].
x is not undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.

Quand vous faites la vérification comme ceci: typeof x === 'undefined', vous demandez essentiellement ceci: Veuillez vérifier si la variable x existe (a été définie) quelque part dans le code source. (plus ou moins). Si vous connaissez C # ou Java, ce type de vérification n'est jamais effectué car s'il n'existe pas, il ne sera pas compilé. 

<== Fiddle Me ==>

1
CodingYoshi

typeof a === 'undefined' est plus rapide que a === 'undefined' d'environ 2 fois sur le noeud v6.9.1.

0
Eduard Popov