Détection d'une propriété d'objet non définie


Réponses:


2681

La façon habituelle de vérifier si la valeur d'une propriété est la valeur spéciale undefinedest la suivante:

if(o.myProperty === undefined) {
  alert("myProperty value is the special value `undefined`");
}

Pour vérifier si un objet ne possède pas réellement une telle propriété, et reviendra donc undefinedpar défaut lorsque vous essayez d'y accéder:

if(!o.hasOwnProperty('myProperty')) {
  alert("myProperty does not exist");
}

Pour vérifier si la valeur associée à un identifiant est la valeur spéciale undefined, ou si cet identifiant n'a pas été déclaré. Remarque: cette méthode est la seule façon de se référer à un identifiant non déclaré (note: différent d'avoir une valeur de undefined) sans erreur précoce:

if(typeof myVariable === 'undefined') {
  alert('myVariable is either the special value `undefined`, or it has not been declared');
}

Dans les versions de JavaScript antérieures à ECMAScript 5, la propriété nommée "undefined" sur l'objet global était accessible en écriture, et par conséquent une simple vérification foo === undefinedpouvait se comporter de manière inattendue si elle avait été accidentellement redéfinie. En JavaScript moderne, la propriété est en lecture seule.

Cependant, dans JavaScript moderne, "undefined" n'est pas un mot-clé, et donc les variables à l'intérieur des fonctions peuvent être nommées "undefined" et masquer la propriété globale.

Si vous êtes préoccupé par ce cas de bord (peu probable), vous pouvez utiliser l'opérateur void pour obtenir la undefinedvaleur spéciale elle-même:

if(myVariable === void 0) {
  alert("myVariable is the special value `undefined`");
}

9
si quelque chose est nul, il est défini (comme nul), mais vous pouvez conjuguer les vérifications également. Le détail ennuyeux du code ci-dessus est que vous ne pouvez pas définir une fonction pour la vérifier, eh bien vous pouvez définir la fonction ... mais essayez de l'utiliser.
neu-rah

5
@ neu-rah pourquoi ne pouvez-vous pas écrire une fonction? pourquoi quelque chose comme ça ne fonctionnerait-il pas? Il semble fonctionner pour moi. Y a-t-il un cas que je ne considère pas? jsfiddle.net/djH9N/6
Zack

7
@Zack Vos tests pour isNullorUndefined n'ont pas pris en compte le cas où vous appelez isNullOrUndefined (f) et f n'est pas déclaré (c'est-à-dire lorsqu'il n'y a pas de déclaration "var f").
pnkfelix

109
Blah, des milliers de votes maintenant. C'est la pire façon possible de le faire. J'espère que les passants voient ce commentaire et décident de vérifier… ahem… d' autres réponses.
Ry-

17
Vous pouvez simplement utiliser obj !== undefinedmaintenant. undefinedutilisé pour être mutable, comme undefined = 1234ce qui entraînerait des résultats intéressants. Mais après Ecmascript 5, il n'est plus accessible en écriture, nous pouvons donc utiliser la version plus simple. codereadability.com/how-to-check-for-undefined-in-javascript
Bruno Buccolo

899

Je pense qu'il existe un certain nombre de réponses incorrectes à ce sujet. Contrairement à la croyance courante, "non défini" n'est pas un mot clé en JavaScript et peut en fait avoir une valeur qui lui est affectée.

Code correct

La façon la plus robuste d'effectuer ce test est:

if (typeof myVar === "undefined")

Cela retournera toujours le résultat correct et gère même la situation où myVarn'est pas déclaré.

Code dégénéré. NE PAS UTILISER.

var undefined = false;  // Shockingly, this is completely legal!
if (myVar === undefined) {
    alert("You have been misled. Run away!");
}

En outre, myVar === undefinedgénérera une erreur dans la situation où myVar n'est pas déclaré.


133
+1 pour avoir noté que myVar === undefined soulèvera une erreur si myVar n'a pas été déclaré
Enrique

73
Je trouve la première justification donnée ici pour ne pas utiliser === undefineddéroutant. Oui, vous pouvez l'affecter à undefined, mais il n'y a aucune raison légitime de le faire et il est prévisible que cela puisse briser votre code. En C, vous pouvez #define true false, et en Python, vous pouvez attribuer à Trueet False, mais les gens ne ressentent pas le besoin de concevoir leur code dans ces langages de manière à se protéger contre la possibilité de saboter délibérément leur propre environnement ailleurs dans le code . Pourquoi la possibilité d'attribuer à undefinedmérite-t-elle même d'être envisagée ici?
Mark Amery

19
en plus des commentaires de Marks, je n'obtiens pas ceci: "myVar === undefined générera une erreur dans la situation où myVar n'est pas déclaré." - pourquoi est-ce mauvais? Pourquoi ne voudrais-je pas avoir d'erreur si je fais référence à des variables non déclarées?
eis

5
Gardez également à l'esprit que vous pouvez toujours faire void 0pour obtenir la valeur qui undefinedpointe vers. Vous pouvez donc le faire if (myVar === void 0). le 0n'est pas spécial, vous pouvez littéralement y mettre n'importe quelle expression.
Claudiu

28
Dans les navigateurs modernes (FF4 +, IE9 +, Chrome inconnu), il n'est plus possible de modifier undefined. MDN: undefined
user247702

228

Bien qu'il soit vivement recommandé par de nombreuses autres réponses ici, typeof c'est un mauvais choix . Il ne doit jamais être utilisé pour vérifier si les variables ont la valeur undefined, car il agit comme une vérification combinée de la valeur undefinedet si une variable existe. Dans la grande majorité des cas, vous savez quand une variable existe, et vous typeofintroduirez simplement le potentiel d'un échec silencieux si vous faites une faute de frappe dans le nom de la variable ou dans le littéral de chaîne 'undefined'.

var snapshot = …;

if (typeof snaposhot === 'undefined') {
    //         ^
    // misspelled¹ – this will never run, but it won’t throw an error!
}
var foo = …;

if (typeof foo === 'undefned') {
    //                   ^
    // misspelled – this will never run, but it won’t throw an error!
}

Donc, à moins que vous ne fassiez de la détection de fonctionnalités², où il y a une incertitude quant à la portée d'un nom donné (comme la vérification en typeof module !== 'undefined'tant qu'étape de code spécifique à un environnement CommonJS), typeofest un choix nuisible lorsqu'il est utilisé sur une variable, et l'option correcte est pour comparer directement la valeur:

var foo = …;

if (foo === undefined) {
    
}

Voici quelques idées fausses courantes à ce sujet:

  • que la lecture d'une variable ( var foo) ou d'un paramètre (non function bar(foo) { … }appelé bar()) (non appelé ) échouera. Ce n'est tout simplement pas vrai - les variables sans initialisation explicite et les paramètres qui n'ont pas reçu de valeurs deviennent toujours undefined, et sont toujours dans la portée.

  • qui undefinedpeut être écrasé. Il y a beaucoup plus à cela. undefinedn'est pas un mot clé en JavaScript. Au lieu de cela, c'est une propriété sur l'objet global avec la valeur Undefined. Cependant, depuis ES5, cette propriété est en lecture seule et non configurable . Aucun navigateur moderne ne permettra de modifier la undefinedpropriété, et depuis 2017, cela a été le cas depuis longtemps. Le manque de mode strict n'affecte pas non plus undefinedle comportement de - il fait juste des instructions comme undefined = 5ne rien faire au lieu de lancer. Comme il ne s'agit pas d'un mot clé, vous pouvez déclarer des variables avec le nom undefined, et ces variables peuvent être modifiées, ce qui rend ce modèle autrefois commun:

    (function (undefined) {
        // …
    })()

    plus dangereux que d'utiliser le global undefined. Si vous devez être compatible ES3, remplacez-le undefinedpar void 0- ne pas y recourir typeof. ( voida toujours été un opérateur unaire qui évalue la valeur non définie pour n'importe quel opérande.)

Avec la façon dont les variables fonctionnent, il est temps de répondre à la question réelle: les propriétés des objets. Il n'y a aucune raison de jamais utiliser typeofpour les propriétés d'objet. L'exception précédente concernant la détection des fonctionnalités ne s'applique pas ici - typeofn'a qu'un comportement spécial sur les variables, et les expressions qui font référence aux propriétés des objets ne sont pas des variables.

Cette:

if (typeof foo.bar === 'undefined') {
    
}

est toujours exactement équivalent à ceci³:

if (foo.bar === undefined) {
    
}

et en tenant compte des conseils ci-dessus, pour éviter de confondre les lecteurs quant à la raison pour laquelle vous utilisez typeof, car il est plus judicieux d'utiliser ===pour vérifier l'égalité, car il pourrait être remanié pour vérifier la valeur d'une variable plus tard, et parce qu'il est tout simplement clair semble mieux, vous devriez toujours utiliser === undefined³ ici aussi .

Une autre chose à considérer en ce qui concerne les propriétés des objets est de savoir si vous voulez vraiment vérifier undefined. Un nom de propriété donné peut être absent sur un objet (produisant la valeur undefinedlors de la lecture), présent sur l'objet lui-même avec la valeur undefined, présent sur le prototype de l'objet avec la valeur undefined, ou présent sur l'un de ceux avec une non- undefinedvaleur. 'key' in objvous dira si une clé se trouve n'importe où sur la chaîne de prototype d'un objet et Object.prototype.hasOwnProperty.call(obj, 'key')vous dira si elle se trouve directement sur l'objet. Je n'entrerai pas dans les détails dans cette réponse sur les prototypes et l'utilisation d'objets comme cartes à chaînes de caractères, car cela est principalement destiné à contrer tous les mauvais conseils dans les autres réponses, quelles que soient les interprétations possibles de la question d'origine. Lire surprototypes d'objets sur MDN pour plus!

¹ choix inhabituel d'exemple de nom de variable? c'est du vrai code mort de l'extension NoScript pour Firefox.
² ne présumez pas que ne pas savoir ce qui est dans la portée est bien en général, cependant. vulnérabilité supplémentaire causée par un abus de portée dynamique: Project Zero 1225
³ supposant une fois de plus un environnement ES5 + et qui se undefinedréfère à la undefinedpropriété de l'objet global. remplacer void 0autrement.


@BenjaminGruenbaum Vrai mais complètement trompeur. Tout contexte non par défaut peut définir le sien undefined, masquant celui par défaut. Ce qui, à des fins pratiques, a le même effet que de l'écraser.
blgt

23
@blgt C'est paranoïaque et inutile pour tout ce qui est pratique. Chaque contexte peut remplacer console.log, redéfinir les méthodes du prototype de tableau et même remplacer le hook de Function.prototype.call, et modifier chaque fois que vous appelez une fonction en JavaScript. Se protéger contre cela est très paranoïaque et plutôt idiot. Comme je l'ai dit (et minitech), vous pouvez utiliser void 0pour comparer avec indéfini mais encore une fois - c'est idiot et exagéré.
Benjamin Gruenbaum

19
J'aimerais avoir plus d'une voix positive à donner. C'est la réponse la plus correcte. Je veux vraiment arrêter de voir typeof something === "undefined") dans le code.
Simon Baumgardt-Wellander

@BenjaminGruenbaum Pour les programmeurs paresseux, void 0c'est (pour une fois) à la fois plus court et plus sûr! C'est une victoire dans mon livre.
wizzwizz4

4
Cela devrait vraiment être la réponse acceptée. C'est le plus complet et le plus à jour.
Patrick Michaelsen

161

En JavaScript, il y a null et il n'y a pas de définition . Ils ont des significations différentes.

  • undefined signifie que la valeur de la variable n'a pas été définie; on ne sait pas quelle est la valeur.
  • null signifie que la valeur de la variable est définie et définie sur null (n'a pas de valeur).

Marijn Haverbeke déclare, dans son livre en ligne gratuit " Eloquent JavaScript " (c'est moi qui souligne):

Il existe également une valeur similaire, null, dont la signification est «cette valeur est définie, mais elle n'a pas de valeur». La différence de sens entre indéfini et nul est principalement académique et généralement peu intéressante. Dans les programmes pratiques, il est souvent nécessaire de vérifier si quelque chose «a une valeur». Dans ces cas, l'expression quelque chose == undefined peut être utilisée, car, même si elles ne sont pas exactement la même valeur, null == undefined produira true.

Donc, je suppose que la meilleure façon de vérifier si quelque chose n'était pas défini serait:

if (something == undefined)

J'espère que cela t'aides!

Modifier: En réponse à votre modification, les propriétés des objets devraient fonctionner de la même manière.

var person = {
    name: "John",
    age: 28,
    sex: "male"
};

alert(person.name); // "John"
alert(person.fakeVariable); // undefined

42
si (quelque chose == indéfini) est mieux écrit comme si (quelque chose === indéfini)
Sebastian Rittau

59
Il convient de souligner que ce n'est pas entièrement sûr. undefinedest juste une variable qui peut être réassignée par l'utilisateur: l'écriture undefined = 'a';fera que votre code ne fera plus ce que vous pensez qu'il fait. L'utilisation typeofest meilleure et fonctionne également pour les variables (pas seulement les propriétés) qui n'ont pas été déclarées.
Gabe Moothart

7
si quelque chose est une variable globale non définie, (quelque chose == non défini) fait apparaître une erreur javascript.
Morgan Cheng

8
Le problème avec ceci est que si var a = null alors a == undefined est évalué à true, même si a est très certainement défini.
Andrew

6
Cette interprétation du commentaire "Eloquent Javascript" est à rebours . Si vous voulez vraiment vérifier non défini, le code suggéré ne fonctionnera pas (il détectera également la condition définie mais aucune valeur n'a encore été définie [ienull]). Une valeur nulle. Le code suggéré "si (quelque chose == non défini) ..." vérifie à la fois non défini et nul (pas de valeur définie), c'est-à-dire qu'il est interprété comme "si ((quelque chose n'est pas défini) OU (quelque chose est nul)) ..." Ce que l'auteur dit, c'est que souvent ce que vous voulez vraiment, c'est vérifier à la fois non défini et nul.
Chuck Kollars

125

Qu'est-ce que cela signifie: "propriété d'objet non définie" ?

En fait, cela peut signifier deux choses bien différentes! Premièrement, cela peut signifier la propriété qui n'a jamais été définie dans l'objet et, deuxièmement, cela peut signifier la propriété qui a une valeur indéfinie . Regardons ce code:

var o = { a: undefined }

Est o.aindéfini? Oui! Sa valeur n'est pas définie. Est o.bindéfini? Sûr! Il n'y a aucune propriété «b» du tout! OK, voyez maintenant comment les différentes approches se comportent dans les deux situations:

typeof o.a == 'undefined' // true
typeof o.b == 'undefined' // true
o.a === undefined // true
o.b === undefined // true
'a' in o // true
'b' in o // false

Nous pouvons clairement voir cela typeof obj.prop == 'undefined'etobj.prop === undefined sont équivalents, et ils ne distinguent pas ces différentes situations. Et 'prop' in objpeut détecter la situation où une propriété n'a pas été définie du tout et ne fait pas attention à la valeur de la propriété qui peut être indéfinie.

Alors que faire?

1) Vous voulez savoir si une propriété n'est pas définie par la première ou la deuxième signification (la situation la plus typique).

obj.prop === undefined // IMHO, see "final fight" below

2) Vous voulez simplement savoir si l'objet a une propriété et ne vous souciez pas de sa valeur.

'prop' in obj

Remarques:

  • Vous ne pouvez pas vérifier un objet et sa propriété en même temps. Par exemple, ceci x.a === undefinedou cela typeof x.a == 'undefined'augmente ReferenceError: x is not definedsi x n'est pas défini.
  • La variable undefinedest une variable globale (elle se trouve donc window.undefineddans les navigateurs). Il est pris en charge depuis ECMAScript 1st Edition et depuis ECMAScript 5, il est en lecture seule . Donc, dans les navigateurs modernes, cela ne peut pas être redéfini sur vrai car de nombreux auteurs aiment nous faire peur, mais cela reste vrai pour les navigateurs plus anciens.

Combat final: obj.prop === undefined vstypeof obj.prop == 'undefined'

Avantages de obj.prop === undefined:

  • Il est un peu plus court et semble un peu plus joli
  • Le moteur JavaScript vous donnera une erreur si vous avez mal orthographié undefined

Moins de obj.prop === undefined:

  • undefined peut être remplacé dans les anciens navigateurs

Avantages de typeof obj.prop == 'undefined':

  • C'est vraiment universel! Il fonctionne dans les nouveaux et anciens navigateurs.

Moins de typeof obj.prop == 'undefined':

  • 'undefned'( mal orthographié ) voici juste une constante de chaîne, donc le moteur JavaScript ne peut pas vous aider si vous l'avez mal orthographié comme je viens de le faire.

Mise à jour (pour JavaScript côté serveur):

Node.js prend en charge la variable globale undefinedas global.undefined(elle peut également être utilisée sans le préfixe «global»). Je ne connais pas les autres implémentations de JavaScript côté serveur.


@Bergi merci pour votre commentaire. J'ai corrigé ma réponse. Pour ma défense, je peux dire qu'actuellement (à partir de la version 1.0.10.18), la documentation officielle de Node.js ne dit rien en undefinedtant que membre de global. De plus, console.log(global);ni for (var key in global) { ... }ne s'affiche pas indéfini en tant que membre de global . Mais tester comme 'undefined' in globalmontrer le contraire.
Konstantin Smolyanin

4
Il n'a pas eu besoin de documentation supplémentaire car il se trouve dans la spécification EcmaScript , ce qui indique également que [[Enumerable]]c'est faux :-)
Bergi

5
Concernant Minuses of typeof obj.prop == 'undefined', cela peut être évité en écrivant comme typeof obj.prop == typeof undefined. Cela donne également une symétrie très agréable.
hlovdal

3
@hlovdal: C'est tout à fait inutile contre obj.prop === undefined.
Ry-

1
Lorsque nous sommes fidèles au titre de la question « Détecter une propriété non définie» , pas à la question (différente et beaucoup plus facile) dans la première phrase («cochez si non définie ...»), vous répondez if ('foo' in o)… votre réponse est vraiment la première bonne réponse ici. Presque tout le monde répond à cette phrase.
Frank Nocke

70

Le problème se résume à trois cas:

  1. L'objet a la propriété et sa valeur ne l'est pas undefined.
  2. L'objet a la propriété et sa valeur est undefined.
  3. L'objet n'a pas la propriété.

Cela nous dit quelque chose que je considère important:

Il existe une différence entre un membre non défini et un membre défini avec une valeur non définie.

Mais malheureusement, typeof obj.foone nous dit pas lequel des trois cas nous avons. Cependant, nous pouvons combiner cela avec "foo" in objpour distinguer les cas.

                               |  typeof obj.x === 'undefined' | !("x" in obj)
1.                     { x:1 } |  false                        | false
2.    { x : (function(){})() } |  true                         | false
3.                          {} |  true                         | true

Il convient de noter que ces tests sont également les mêmes pour les nullentrées

                               |  typeof obj.x === 'undefined' | !("x" in obj)
                    { x:null } |  false                        | false

Je dirais que dans certains cas, il est plus logique (et plus clair) de vérifier si la propriété est là, que de vérifier si elle n'est pas définie, et le seul cas où cette vérification sera différente est le cas 2, le rare cas de une entrée réelle dans l'objet avec une valeur non définie.

Par exemple: je viens de refactoriser un tas de code qui avait un tas de vérifications si un objet avait une propriété donnée.

if( typeof blob.x != 'undefined' ) {  fn(blob.x); }

Ce qui était plus clair lorsqu'il était écrit sans vérification pour indéfini.

if( "x" in blob ) { fn(blob.x); }

Mais comme cela a été mentionné, ce ne sont pas exactement les mêmes (mais ils sont plus que suffisants pour mes besoins).


10
Salut michael. Excellente suggestion, et je pense que cela rend les choses plus propres. Un problème que j'ai trouvé, cependant, est en utilisant le! opérateur avec "in". Vous devez dire if (!("x" in blob)) {}avec des crochets autour de l'intérieur, car le! L'opérateur a la priorité sur «in». J'espère que cela aide quelqu'un.
Simon East

Désolé Michael, mais c'est incorrect, ou du moins trompeur, à la lumière de la question d'origine. 'in' n'est pas un moyen suffisant pour tester si une propriété d'objet a le typeof indéfini. Pour la preuve, veuillez consulter ce violon: jsfiddle.net/CsLKJ/4
tex

2
Ces deux parties de code font une chose différente! Considérez et objectez donné par a = {b: undefined}; alors typeof a.b === typeof a.c === 'undefined'mais 'b' in aet !('c' in a).
mgol

3
+1. L'OP ne précise pas si la propriété existe et a la valeur non définie , ou si la propriété elle-même n'est pas définie (c'est-à-dire n'existe pas).
RobG

Je suggérerais de changer le point (2.) dans votre premier tableau pour l' { x : undefined }ajouter ou du moins comme une autre alternative à (2.) dans le tableau - j'ai dû réfléchir un instant pour réaliser que le point (2.) correspond à undefined(bien que vous en parlez plus tard).
mucaho

46
if ( typeof( something ) == "undefined") 

Cela a fonctionné pour moi tandis que les autres ne l'ont pas fait.


47
les parens ne sont pas nécessaires puisque typeof est un opérateur
aehlke

12
Mais ils clarifient ce qui est vérifié. Sinon, il pourrait être lu comme typeof (something == "undefined").
Abhi Beckert

Si vous avez besoin des parenthèses, vous devez apprendre la priorité des opérateurs dans JS: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Ian

11
Les parenthèses sont utiles précisément parce que vous n'avez PAS besoin d'apprendre la priorité des opérateurs dans JS, ni de spéculer si les futurs programmeurs de maintenance devront apprendre la priorité des opérateurs dans JS.
DaveWalley

27
Les parenthèses sont utiles pour clarifier les choses. Mais dans ce cas, ils font simplement ressembler l'opérateur à une fonction. Cela clarifie sans aucun doute l'intention du programmeur. Mais si vous n'êtes pas sûr de la priorité de l'opérateur, vous devriez plutôt l'écrire sous la forme (typeof something) === "undefined".
Robert

42

Je ne sais pas d'où vient l'utilisation de ===with typeof, et comme convention je le vois utilisé dans de nombreuses bibliothèques, mais l'opérateur typeof renvoie un littéral de chaîne, et nous le savons d'avance, alors pourquoi voudriez-vous également taper vérifier aussi?

typeof x;                      // some string literal "string", "object", "undefined"
if (typeof x === "string") {   // === is redundant because we already know typeof returns a string literal
if (typeof x == "string") {    // sufficient

Excellent point Eric. Y a-t-il également un impact sur les performances de la vérification du type?
Simon East

5
@Simon: bien au contraire - on pourrait s'attendre à une légère baisse des performances en évitant la contrainte dans le cas '==='. Un test rapide et sale a montré que '===' est 5% plus rapide que '==' sous FF5.0.1
Antony Hatchkins

5
Un test plus approfondi a montré que sous FF, IE et Chrome, '==' est plus ou moins rapide que '===' (5-10%) et Opera ne fait aucune différence: jsperf.com/triple- est égal à deux fois égal / 6
Antony Hatchkins

3
L'utilisation ==nécessite toujours au moins une vérification de type - l'interpréteur ne peut pas comparer les deux opérandes sans connaître d'abord leur type.
Alnitak

7
==est un caractère de moins que ===:)
svidgen

25

Crossposting ma réponse à partir d'une question connexe Comment vérifier si "non défini" en JavaScript?

Spécifique à cette question, voir les cas de test avec someObject.<whatever>.


Quelques scénarios illustrant les résultats des différentes réponses: http://jsfiddle.net/drzaus/UVjM4/

(Notez que l'utilisation de varpour les intests fait une différence dans un wrapper de portée)

Code de référence:

(function(undefined) {
    var definedButNotInitialized;
    definedAndInitialized = 3;
    someObject = {
        firstProp: "1"
        , secondProp: false
        // , undefinedProp not defined
    }
    // var notDefined;

    var tests = [
        'definedButNotInitialized in window',
        'definedAndInitialized in window',
        'someObject.firstProp in window',
        'someObject.secondProp in window',
        'someObject.undefinedProp in window',
        'notDefined in window',

        '"definedButNotInitialized" in window',
        '"definedAndInitialized" in window',
        '"someObject.firstProp" in window',
        '"someObject.secondProp" in window',
        '"someObject.undefinedProp" in window',
        '"notDefined" in window',

        'typeof definedButNotInitialized == "undefined"',
        'typeof definedButNotInitialized === typeof undefined',
        'definedButNotInitialized === undefined',
        '! definedButNotInitialized',
        '!! definedButNotInitialized',

        'typeof definedAndInitialized == "undefined"',
        'typeof definedAndInitialized === typeof undefined',
        'definedAndInitialized === undefined',
        '! definedAndInitialized',
        '!! definedAndInitialized',

        'typeof someObject.firstProp == "undefined"',
        'typeof someObject.firstProp === typeof undefined',
        'someObject.firstProp === undefined',
        '! someObject.firstProp',
        '!! someObject.firstProp',

        'typeof someObject.secondProp == "undefined"',
        'typeof someObject.secondProp === typeof undefined',
        'someObject.secondProp === undefined',
        '! someObject.secondProp',
        '!! someObject.secondProp',

        'typeof someObject.undefinedProp == "undefined"',
        'typeof someObject.undefinedProp === typeof undefined',
        'someObject.undefinedProp === undefined',
        '! someObject.undefinedProp',
        '!! someObject.undefinedProp',

        'typeof notDefined == "undefined"',
        'typeof notDefined === typeof undefined',
        'notDefined === undefined',
        '! notDefined',
        '!! notDefined'
    ];

    var output = document.getElementById('results');
    var result = '';
    for(var t in tests) {
        if( !tests.hasOwnProperty(t) ) continue; // bleh

        try {
            result = eval(tests[t]);
        } catch(ex) {
            result = 'Exception--' + ex;
        }
        console.log(tests[t], result);
        output.innerHTML += "\n" + tests[t] + ": " + result;
    }
})();

Et les résultats:

definedButNotInitialized in window: true
definedAndInitialized in window: false
someObject.firstProp in window: false
someObject.secondProp in window: false
someObject.undefinedProp in window: true
notDefined in window: Exception--ReferenceError: notDefined is not defined
"definedButNotInitialized" in window: false
"definedAndInitialized" in window: true
"someObject.firstProp" in window: false
"someObject.secondProp" in window: false
"someObject.undefinedProp" in window: false
"notDefined" in window: false
typeof definedButNotInitialized == "undefined": true
typeof definedButNotInitialized === typeof undefined: true
definedButNotInitialized === undefined: true
! definedButNotInitialized: true
!! definedButNotInitialized: false
typeof definedAndInitialized == "undefined": false
typeof definedAndInitialized === typeof undefined: false
definedAndInitialized === undefined: false
! definedAndInitialized: false
!! definedAndInitialized: true
typeof someObject.firstProp == "undefined": false
typeof someObject.firstProp === typeof undefined: false
someObject.firstProp === undefined: false
! someObject.firstProp: false
!! someObject.firstProp: true
typeof someObject.secondProp == "undefined": false
typeof someObject.secondProp === typeof undefined: false
someObject.secondProp === undefined: false
! someObject.secondProp: true
!! someObject.secondProp: false
typeof someObject.undefinedProp == "undefined": true
typeof someObject.undefinedProp === typeof undefined: true
someObject.undefinedProp === undefined: true
! someObject.undefinedProp: true
!! someObject.undefinedProp: false
typeof notDefined == "undefined": true
typeof notDefined === typeof undefined: true
notDefined === undefined: Exception--ReferenceError: notDefined is not defined
! notDefined: Exception--ReferenceError: notDefined is not defined
!! notDefined: Exception--ReferenceError: notDefined is not defined

21

Si tu fais

if (myvar == undefined )
{ 
    alert('var does not exists or is not initialized');
}

il échouera lorsque la variable myvar n'existe pas, car myvar n'est pas défini, donc le script est cassé et le test n'a aucun effet.

Étant donné que l'objet fenêtre a une portée globale (objet par défaut) en dehors d'une fonction, une déclaration sera «attachée» à l'objet fenêtre.

Par exemple:

var myvar = 'test';

La variable globale myvar est la même que window.myvar ou window ['myvar']

Pour éviter les erreurs de test lorsqu'une variable globale existe, il vaut mieux utiliser:

if(window.myvar == undefined )
{ 
    alert('var does not exists or is not initialized');
}

La question de savoir si une variable existe vraiment n'a pas d'importance, sa valeur est incorrecte. Sinon, il est stupide d'initialiser des variables avec undefined, et il vaut mieux utiliser la valeur false pour initialiser. Lorsque vous savez que toutes les variables que vous déclarez sont initialisées avec false, vous pouvez simplement vérifier son type ou vous fier !window.myvarà vérifier si elle a une valeur correcte / valide. Ainsi, même lorsque la variable n'est pas définie, il en !window.myvarva de même pour myvar = undefinedou myvar = falseoumyvar = 0 .

Lorsque vous attendez un type spécifique, testez le type de la variable. Pour accélérer le test d'une condition, il vaut mieux:

if( !window.myvar || typeof window.myvar != 'string' )
{
    alert('var does not exists or is not type of string');
}

Lorsque la première et simple condition est remplie, l'interpréteur ignore les tests suivants.

Il est toujours préférable d'utiliser l'instance / l'objet de la variable pour vérifier si elle a obtenu une valeur valide. Il est plus stable et constitue un meilleur moyen de programmation.

(y)


19

Je n'ai vu (j'espère pas l'avoir manqué) quiconque vérifier l'objet avant la propriété. C'est donc le plus court et le plus efficace (mais pas forcément le plus clair):

if (obj && obj.prop) {
  // Do something;
}

Si obj ou obj.prop est indéfini, nul ou "falsifié", l'instruction if n'exécutera pas le bloc de code. Il s'agit généralement du comportement souhaité dans la plupart des instructions de bloc de code (en JavaScript).


2
Si vous voulez savoir pourquoi cela fonctionne: Javascript: opérateurs logiques et vérité / fausse
mb21

si vous voulez affecter la propriété à une variable si elle est définie, pas null et pas falsey, sinon utilisez une valeur par défaut, vous pouvez utiliser: var x = obj && obj.prop || 'default';
Stijn de Witt

Je crois que la question est de vérifier par rapport à undefined explicitement. Votre condition vérifie toutes les fausses valeurs de JS.
NikoKyriakid

15

Dans l'article Exploring the Abyss of Null and Undefined in JavaScript, j'ai lu que les frameworks comme Underscore.js utilisent cette fonction:

function isUndefined(obj){
    return obj === void 0;
}

3
void 0est juste une courte façon d'écrire undefined(puisque c'est ce que void suivi de toute expression renvoie), il enregistre 3 caractères. Cela pourrait aussi faire l'affaire var a; return obj === a;, mais c'est un personnage de plus. :-)
RobG

2
voidest un mot réservé, alors qu'il undefinedn'est pas ie tandis que undefinedest égal à void 0par défaut, vous pouvez assigner une valeur à undefinedeg undefined = 1234.
Brian M. Hunt,

isUndefined(obj): 16 caractères. obj === void 0: 14 caractères. dit-il.
Stijn de Witt,

14

Tout simplement, tout n'est pas défini en JavaScript, n'est pas défini , peu importe qu'il s'agisse d'une propriété à l'intérieur d'un objet / tableau ou simplement d'une simple variable ...

JavaScript a typeofqui le rend très facile à détecter une variable non définie.

Vérifiez simplement si typeof whatever === 'undefined'et cela renverra un booléen.

C'est ainsi que la célèbre fonction isUndefined()d'AngularJs v.1x s'écrit:

function isUndefined(value) {return typeof value === 'undefined';} 

Donc, comme vous voyez que la fonction reçoit une valeur, si cette valeur est définie, elle retournera false, sinon pour les valeurs non définies, retournera true.

Voyons donc quels seront les résultats lorsque nous passerons des valeurs, y compris les propriétés des objets comme ci-dessous, voici la liste des variables que nous avons:

var stackoverflow = {};
stackoverflow.javascipt = 'javascript';
var today;
var self = this;
var num = 8;
var list = [1, 2, 3, 4, 5];
var y = null;

et nous les vérifions comme ci-dessous, vous pouvez voir les résultats devant eux sous forme de commentaire:

isUndefined(stackoverflow); //false
isUndefined(stackoverflow.javascipt); //false
isUndefined(today); //true
isUndefined(self); //false
isUndefined(num); //false
isUndefined(list); //false
isUndefined(y); //false
isUndefined(stackoverflow.java); //true
isUndefined(stackoverflow.php); //true
isUndefined(stackoverflow && stackoverflow.css); //true

Comme vous le voyez, nous pouvons tout vérifier en utilisant quelque chose comme ça dans notre code, comme mentionné, vous pouvez simplement l'utiliser typeofdans votre code, mais si vous l'utilisez encore et encore, créez une fonction comme l'exemple angulaire que je partage et continue à réutiliser comme suivant le modèle de code DRY.

Encore une chose, pour vérifier la propriété d'un objet dans une application réelle dont vous n'êtes pas sûr que l'objet existe ou non, vérifiez si l'objet existe en premier.

Si vous vérifiez une propriété sur un objet et que cet objet n’existe pas, une erreur se produit et l’application entière s'arrête.

isUndefined(x.css);
VM808:2 Uncaught ReferenceError: x is not defined(…)

Si simple que vous pouvez envelopper une instruction if comme ci-dessous:

if(typeof x !== 'undefined') {
  //do something
}

Qui est également égal à isDefined dans Angular 1.x ...

function isDefined(value) {return typeof value !== 'undefined';}

D'autres frameworks javascript comme le soulignement ont également une vérification de définition similaire, mais je vous recommande d'utiliser typeofsi vous n'utilisez déjà aucun framework.

J'ajoute également cette section de MDN qui a obtenu des informations utiles sur typeof, undefined et void (0).

Égalité stricte et non défini
Vous pouvez utiliser les opérateurs undefined et stricte d'égalité et d'inégalité pour déterminer si une variable a une valeur. Dans le code suivant, la variable x n'est pas définie et l'instruction if prend la valeur true.

var x;
if (x === undefined) {
   // these statements execute
}
else {
   // these statements do not execute
}

Remarque: L'opérateur d'égalité stricte plutôt que l'opérateur d'égalité standard doit être utilisé ici, car x == non défini vérifie également si x est nul, contrairement à l'égalité stricte. null n'est pas équivalent à undefined. Voir les opérateurs de comparaison pour plus de détails.


Opérateur typeof et indéfini
Alternativement, typeof peut être utilisé:

var x;
if (typeof x === 'undefined') {
   // these statements execute
}

L'une des raisons d'utiliser typeof est qu'il ne génère pas d'erreur si la variable n'a pas été déclarée.

// x has not been declared before
if (typeof x === 'undefined') { // evaluates to true without errors
   // these statements execute
}

if (x === undefined) { // throws a ReferenceError

}

Cependant, ce type de technique doit être évité. JavaScript est un langage à portée statique, donc savoir si une variable est déclarée peut être lu en voyant si elle est déclarée dans un contexte englobant. La seule exception est la portée globale, mais la portée globale est liée à l'objet global, donc la vérification de l'existence d'une variable dans le contexte global peut être effectuée en vérifiant l'existence d'une propriété sur l'objet global (en utilisant l'opérateur in, par exemple).


Opérateur nul et non défini

L'opérateur void est une troisième alternative.

var x;
if (x === void 0) {
   // these statements execute
}

// y has not been declared before
if (y === void 0) {
   // throws a ReferenceError (in contrast to `typeof`)
}

plus> ici


13

' if (window.x) {} ' est protégé contre les erreurs

Vous le souhaitez très probablement if (window.x). Cette vérification est sûre même si x n'a pas été déclaré ( var x;) - le navigateur ne génère pas d'erreur.

Exemple: je veux savoir si mon navigateur prend en charge l'API Historique

if (window.history) {
    history.call_some_function();
}

Comment cela fonctionne:

window est un objet qui contient toutes les variables globales en tant que membres, et il est légal d'essayer d'accéder à un membre inexistant. Si x n'a pas été déclaré ou n'a pas été défini, window.xretourne undefined . undefined conduit à false lorsque if () l' évalue.


Mais que faire si vous exécutez dans Node? typeof history != 'undefined'fonctionne réellement dans les deux systèmes.
Stijn de Witt,

13

En lisant ceci, je suis étonné de ne pas l'avoir vu. J'ai trouvé plusieurs algorithmes qui fonctionneraient pour cela.

Jamais défini

Si la valeur d'un objet n'a jamais été définie, cela empêchera de revenir trues'il est défini comme nullou undefined. Cela est utile si vous souhaitez que true soit renvoyé pour les valeurs définies commeundefined

if(obj.prop === void 0) console.log("The value has never been defined");

Défini comme indéfini ou jamais défini

Si vous voulez que cela résulte comme truepour les valeurs définies avec la valeur de undefined, ou jamais définies, vous pouvez simplement utiliser=== undefined

if(obj.prop === undefined) console.log("The value is defined as undefined, or never defined");

Défini comme une valeur falsifiée, non défini, nul ou jamais défini.

Généralement, les gens m'ont demandé un algorithme pour déterminer si une valeur est soit fausse undefined, soit null. Les œuvres suivantes.

if(obj.prop == false || obj.prop === null || obj.prop === undefined) {
    console.log("The value is falsy, null, or undefined");
}

4
Je pense que vous pouvez remplacer le dernier exemple parif (!obj.prop)
Stijn de Witt

@StijndeWitt, vous pouvez, j'étais assez inexpérimenté quand j'ai écrit cela, et mon anglais semble avoir été tout aussi mauvais, néanmoins, il n'y a rien de mal dans la réponse
Travis

3
var obj = {foo: undefined}; obj.foo === void 0-> true. Comment est-ce "jamais défini comme undefined"? C'est faux.
Patrick Roberts

@PatrickRoberts Vous avez raison. Lorsque j'ai écrit cette réponse en février 2015 (avant ES6), la première option que j'ai décrite a bien fonctionné, mais elle est désormais obsolète.
Travis

12
"propertyName" in obj //-> true | false

10

Comparez avec void 0, pour la concision.

if (foo !== void 0)

Ce n'est pas aussi verbeux que if (typeof foo !== 'undefined')


3
Mais il lancera une ReferenceError s'il foon'est pas déclaré.
daniel1426

1
@ daniel1426: Donc s'il y a une erreur dans votre code, vous voulez le cacher au lieu de le corriger? Pas une bonne approche, OMI.

Ceci n'est pas utilisé pour masquer les erreurs. C'est la manière courante de détecter les propriétés de l'environnement pour définir les polyfills. Par exemple: if (typeof Promise === 'undefined') {/ * define Promise * /}
gaperton

10

La solution est incorrecte. En JavaScript,

null == undefined

retournera vrai, car ils sont tous les deux "castés" en booléens et sont faux. La bonne façon serait de vérifier

if (something === undefined)

qui est l'opérateur d'identité ...


3
Pour être clair, il ===s'agit du type égalité + (égalité primitive | identité d'objet), où les primitives incluent des chaînes. Je pense que la plupart des gens considèrent que ce 'abab'.slice(0,2) === 'abab'.slice(2)n'est pas intuitif si l'on considère ===comme l'opérateur d'identité.
clacke

1
Faux. Cela génère une erreur si la variable n'a pas été créée. Ne devrait pas être voté. Utilisez plutôt typeof.
Simon East

10

Vous pouvez obtenir un tableau non défini avec chemin à l'aide du code suivant.

 function getAllUndefined(object) {

        function convertPath(arr, key) {
            var path = "";
            for (var i = 1; i < arr.length; i++) {

                path += arr[i] + "->";
            }
            path += key;
            return path;
        }


        var stack = [];
        var saveUndefined= [];
        function getUndefiend(obj, key) {

            var t = typeof obj;
            switch (t) {
                case "object":
                    if (t === null) {
                        return false;
                    }
                    break;
                case "string":
                case "number":
                case "boolean":
                case "null":
                    return false;
                default:
                    return true;
            }
            stack.push(key);
            for (k in obj) {
                if (obj.hasOwnProperty(k)) {
                    v = getUndefiend(obj[k], k);
                    if (v) {
                        saveUndefined.push(convertPath(stack, k));
                    }
                }
            }
            stack.pop();

        }

        getUndefiend({
            "": object
        }, "");
        return saveUndefined;
    }

Lien jsFiddle


Bien que cela n'affecte pas la validité de votre code, vous avez une faute de frappe: getUndefienddevrait l'être getUndefined.
icktoofay

8

Voici ma situation:

J'utilise le résultat d'un appel REST. Le résultat doit être analysé à partir de JSON vers un objet JavaScript.

Il y a une erreur que je dois défendre. Si les arguments de l'appel de repos étaient incorrects dans la mesure où l'utilisateur spécifiant les arguments de manière incorrecte, l'appel de repos revient essentiellement vide.

En utilisant ce post pour m'aider à me défendre contre cela, j'ai essayé cela.

if( typeof restResult.data[0] === "undefined" ) { throw  "Some error"; }

Pour ma situation, si restResult.data [0] === "objet", alors je peux commencer en toute sécurité à inspecter le reste des membres. Si non défini, lancez l'erreur comme ci-dessus.

Ce que je dis, c'est que pour ma situation, toutes les suggestions ci-dessus dans ce post n'ont pas fonctionné. Je ne dis pas que j'ai raison et que tout le monde a tort. Je ne suis pas du tout un maître JavaScript, mais j'espère que cela aidera quelqu'un.


Votre typeofgarde ne se garde pas réellement contre tout ce qu'une comparaison directe ne pourrait pas gérer. S'il restResultn'est pas défini ou non déclaré, il sera toujours lancé.

Dans votre cas, vous pouvez plus simplement vérifier si le tableau est vide:if(!restResult.data.length) { throw "Some error"; }
Headbank

8

Il existe un moyen agréable et élégant d’attribuer une propriété définie à une nouvelle variable si elle est définie ou de lui attribuer une valeur par défaut comme solution de rechange si elle n’est pas définie.

var a = obj.prop || defaultValue;

Cela convient si vous avez une fonction, qui reçoit une propriété de configuration supplémentaire:

var yourFunction = function(config){

   this.config = config || {};
   this.yourConfigValue = config.yourConfigValue || 1;
   console.log(this.yourConfigValue);

}

En cours d'exécution

yourFunction({yourConfigValue:2});
//=> 2

yourFunction();
//=> 1

yourFunction({otherProperty:5});
//=> 1

7

Toutes les réponses sont incomplètes. C'est la bonne façon de savoir qu'il existe une propriété «définie comme non définie»:

var hasUndefinedProperty = function hasUndefinedProperty(obj, prop){
  return ((prop in obj) && (typeof obj[prop] == 'undefined')) ;
} ;

Exemple:

var a = { b : 1, e : null } ;
a.c = a.d ;

hasUndefinedProperty(a, 'b') ; // false : b is defined as 1
hasUndefinedProperty(a, 'c') ; // true : c is defined as undefined
hasUndefinedProperty(a, 'd') ; // false : d is undefined
hasUndefinedProperty(a, 'e') ; // false : e is defined as null

// And now...
delete a.c ;
hasUndefinedProperty(a, 'c') ; // false : c is undefined

Dommage que cela ait été la bonne réponse est enterré dans de mauvaises réponses> _ <

Donc, pour tous ceux qui passeront, je vous donnerai des indéfinis gratuitement !!

var undefined ; undefined ; // undefined
({}).a ;                    // undefined
[].a ;                      // undefined
''.a ;                      // undefined
(function(){}()) ;          // undefined
void(0) ;                   // undefined
eval() ;                    // undefined
1..a ;                      // undefined
/a/.a ;                     // undefined
(true).a ;                  // undefined

7

En parcourant les commentaires, pour ceux qui veulent vérifier les deux, c'est indéfini ou sa valeur est nulle:

//Just in JavaScript
var s; // Undefined
if (typeof s == "undefined" || s === null){
    alert('either it is undefined or value is null')
}

Si vous utilisez la bibliothèque jQuery, jQuery.isEmptyObject()cela suffira dans les deux cas,

var s; // Undefined
jQuery.isEmptyObject(s); // Will return true;

s = null; // Defined as null
jQuery.isEmptyObject(s); // Will return true;

//Usage
if (jQuery.isEmptyObject(s)) {
    alert('Either variable:s is undefined or its value is null');
} else {
     alert('variable:s has value ' + s);
}

s = 'something'; // Defined with some value
jQuery.isEmptyObject(s); // Will return false;

jQuery prendra également en charge tous les problèmes de compatibilité entre les navigateurs avec les différentes API JavaScript.
Henry Heleine

7

Si vous utilisez Angular:

angular.isUndefined(obj)
angular.isUndefined(obj.prop)

Underscore.js:

_.isUndefined(obj) 
_.isUndefined(obj.prop) 

2
Comment ajouter 1à une variable x? Ai-je besoin de Underscore ou jQuery? (incroyable que les gens utilisent les bibliothèques même pour les opérations les plus élémentaires comme un typeofchèque)
Stijn de Witt

6

J'utilise if (this.variable)pour tester s'il est défini. Simple if (variable), recommandé ci - dessus , échoue pour moi. Il s'avère que cela ne fonctionne que lorsque la variable est un champ d'un objet, obj.someFieldpour vérifier si elle est définie dans le dictionnaire. Mais nous pouvons utiliser thisou windowcomme objet dictionnaire car toute variable est un champ dans la fenêtre actuelle, si je comprends bien. Voici donc un test

if (this.abc) alert("defined"); else alert("undefined");

abc = "abc";
if (this.abc) alert("defined"); else alert("undefined");

Il détecte d'abord que la variable abcn'est pas définie et elle est définie après l'initialisation.


5

Je propose ici trois façons pour ceux qui attendent des réponses étranges:

function isUndefined1(val) {
    try {
        val.a;
    } catch (e) {
        return /undefined/.test(e.message);
    }
    return false;
}
function isUndefined2(val) {
    return !val && val+'' === 'undefined';
}
function isUndefined3(val) {
    const defaultVal={};
    return ((input=defaultVal)=>input===defaultVal)(val);
}
function test(func){
    console.group(`test start :`+func.name);
    console.log(func(undefined));
    console.log(func(null));
    console.log(func(1));
    console.log(func("1"));
    console.log(func(0));
    console.log(func({}));
    console.log(func(function () { }));
    console.groupEnd();
}
test(isUndefined1);
test(isUndefined2);
test(isUndefined3);

isUndefined1:

Essayez d'obtenir une propriété de la valeur d'entrée, vérifiez le message d'erreur s'il existe. Si la valeur d'entrée n'est pas définie, le message d'erreur serait Uncaught TypeError: Impossible de lire la propriété «b» de non défini

isUndefined2:

Convertir la valeur d'entrée en chaîne pour comparer avec "undefined" et assurez-vous qu'il s'agit d'une valeur négative.

isUndefined3:

Dans js, le paramètre facultatif fonctionne lorsque la valeur d'entrée est exactement undefined.


5

ES2019 a introduit une nouvelle fonctionnalité - chaînage facultatif que vous pouvez utiliser pour utiliser une propriété d'un objet uniquement lorsqu'un objet est défini comme ceci:

const userPhone = user?.contactDetails?.phone;

Il fera référence à la propriété du téléphone uniquement lorsque l'utilisateur et contactDetails sont définis.

Réf. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining


J'utilisais beaucoup la fonction get de lodash, très pratique pour accéder à ce genre d'objets, mais le nouveau chaînage optionnel couvre la plupart des utilisations de _.get
Al Hill il y a

4
function isUnset(inp) {
  return (typeof inp === 'undefined')
}

Renvoie false si la variable est définie et true si n'est pas défini.

Utilisez ensuite:

if (isUnset(var)) {
  // initialize variable here
}

5
Non, ne fais pas ça. Il suffit d'un test très simple pour prouver que vous ne pouvez pas envelopper de manière significative un typeoftest dans une fonction. Étonnant que 4 personnes aient voté pour cela. -1.
Stijn de Witt,

4

Je voudrais vous montrer quelque chose que j'utilise pour protéger la undefinedvariable:

Object.defineProperty(window, 'undefined', {});

Cela interdit à quiconque de modifier la window.undefinedvaleur, détruisant ainsi le code basé sur cette variable. Si vous utilisez "use strict", tout ce qui tente de changer sa valeur se terminera par erreur, sinon il serait ignoré en silence.


4

vous pouvez également utiliser Proxy, cela fonctionnera avec les appels imbriqués, mais nécessitera une vérification supplémentaire:

function resolveUnknownProps(obj, resolveKey) {
  const handler = {
    get(target, key) {
      if (
        target[key] !== null &&
        typeof target[key] === 'object'
      ) {
        return resolveUnknownProps(target[key], resolveKey);
      } else if (!target[key]) {
        return resolveUnknownProps({ [resolveKey]: true }, resolveKey);
      }

      return target[key];
    },
  };

  return new Proxy(obj, handler);
}

const user = {}

console.log(resolveUnknownProps(user, 'isUndefined').personalInfo.name.something.else); // { isUndefined: true }

vous allez donc l'utiliser comme:

const { isUndefined } = resolveUnknownProps(user, 'isUndefined').personalInfo.name.something.else;
if (!isUndefined) {
  // do someting
}
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.