Vérification null JavaScript

170

J'ai rencontré le code suivant:

function test(data) {
    if (data != null && data !== undefined) {
        // some code here
    }
}

Je suis un peu nouveau dans JavaScript, mais, d'après d'autres questions que j'ai lues ici, j'ai l'impression que ce code n'a pas beaucoup de sens.


En particulier, cette réponse indique que

Vous obtiendrez une erreur si vous accédez à une variable non définie dans un contexte autre que typeof.

Mise à jour: La (citation de la) réponse ci-dessus peut être trompeuse. Il devrait dire «une variable non déclarée» , au lieu de «une variable non définie» .

Comme je l'ai découvert, dans les réponses de Ryan ♦ , maerics et nwellnhof , même si aucun argument n'est fourni à une fonction, ses variables pour les arguments sont toujours déclarées. Ce fait prouve également faux le premier élément de la liste ci-dessous.


D'après ce que je comprends, les scénarios suivants peuvent être rencontrés:

  • La fonction a été appelée sans argument, créant ainsi dataune variable non définie et levant une erreur sur data != null.

  • La fonction a été appelée spécifiquement avec null(ou undefined), comme argument, auquel cas data != nullprotège déjà le code interne, le rendant && data !== undefinedinutile.

  • La fonction a été appelée avec un argument non nul, auquel cas elle passera trivialement à la fois data != null et data !== undefined .

Q: Ma compréhension est-elle correcte?


J'ai essayé ce qui suit, dans la console de Firefox:

--
[15:31:31.057] false != null
[15:31:31.061] true
--
[15:31:37.985] false !== undefined
[15:31:37.989] true
--
[15:32:59.934] null != null
[15:32:59.937] false
--
[15:33:05.221] undefined != null
[15:33:05.225] false
--
[15:35:12.231] "" != null
[15:35:12.235] true
--
[15:35:19.214] "" !== undefined
[15:35:19.218] true

Je ne peux pas comprendre un cas où l' data !== undefined après data != null pourrait être d'une quelconque utilité.

Afsantos
la source
9
Utilisez simplement if (data). C'est un moyen Javascript mnémotechnique pour vérifier si la datavariable vaut true. undefined, null, Faux, 0, chaîne vide, tableau vide et objet (?) Sans propriété est évaluée à false, le reste est vrai.
J0HN
20
@ J0HN - Utiliser if(data)signifierait qu'il ne peut pas passer falseou 0comme valeurs pour data.
techfoobar
@ J0HN Aussi, la même réponse que je mentionne indique également que:, if(typeof someUndefVar == whatever) -- workset if(someUnderVar) -- error.
afsantos
2
C'est probablement censé l'être data !== null && data !== undefined, ce qui équivaut à data != nullce qui équivaut à data != undefined. La première forme a tendance à être favorisée car elle est plus explicite sur les conditions, alors qu'il serait facile d'oublier les deux nullet undefinedqu'elles sont vérifiées avec les deux dernières conditions.
zzzzBov
2
En passant, les tests explicites pour undefinedIMO sont une odeur de code. Ce n'est pas un mot-clé protégé comme null, c'est une variable qui se trouve être indéfinie. Ceci est tout à fait valide et va casser votre code:undefined = 1
Izkata

Réponses:

106

Une «variable non définie» est différente de la valeur undefined.

Une variable non définie:

var a;
alert(b); // ReferenceError: b is not defined

Une variable avec la valeur undefined:

var a;
alert(a); // Alerts “undefined”

Lorsqu'une fonction prend un argument, cet argument est toujours déclaré même si sa valeur est undefined, et il n'y aura donc aucune erreur. Vous avez raison d'être != nullsuivi en !== undefinedétant inutile, cependant.

Ry-
la source
32
data !== null && data !== undefinedaurait du sens, cependant.
bfavaretto
@bfavaretto: Oui, donc c'est peut-être en fait une faute de frappe. Mais on ne sait jamais…: D
Ry-
1
Tout comme je le pensais, merci pour la clarification. De plus, je ne pense pas que ce soit une faute de frappe. J'ai exécuté une recherche et un comptage dans tout le script, et il a trouvé 10 occurrences, donc ... Je suppose que l'auteur a également besoin de clarifications à ce sujet.
afsantos
2
Grattez mon commentaire ci-dessus: en fait, data != nullvérifierait les deux nullet undefined(mais, fait intéressant, juste pour nullet undefined, et pas les autres valeurs fausses).
bfavaretto
90

En JavaScript, nullest un objet singleton spécial qui est utile pour signaler "aucune valeur". Vous pouvez le tester par comparaison et, comme d'habitude en JavaScript, c'est une bonne pratique d'utiliser l' ===opérateur pour éviter de confondre la coercition de type:

var a = null;
alert(a === null); // true

Comme le mentionne @rynah, "indéfini" est un peu déroutant en JavaScript. Cependant, il est toujours prudent de tester si la typeof(x)chaîne est "indéfinie", même si "x" n'est pas une variable déclarée:

alert(typeof(x) === 'undefined'); // true

De plus, les variables peuvent avoir la "valeur indéfinie" si elles ne sont pas initialisées:

var y;
alert(typeof(y) === 'undefined'); // true

En mettant tout cela ensemble, votre chèque devrait ressembler à ceci:

if ((typeof(data) !== 'undefined') && (data !== null)) {
  // ...

Cependant, étant donné que la variable "data" est toujours définie car il s'agit d'un paramètre de fonction formel, l'utilisation de l'opérateur "typeof" n'est pas nécessaire et vous pouvez en toute sécurité comparer directement avec la "valeur non définie".

function(data) {
  if ((data !== undefined) && (data !== null)) {
    // ...

Cet extrait revient à dire "si la fonction a été appelée avec un argument défini et non nul ..."

maerics
la source
5
Pourquoi cela devrait- il ressembler à ça? != nullsera vrai pour toutes les valeurs sauf nullet undefined, et nous sommes sûrs que cette variable est déclarée. typeofdans d'autres situations, cela peut même être dangereux - et si vous saisissez mal le nom de la variable? Cela peut passer inaperçu pendant longtemps car il n'y a pas d'erreur.
Ry-
@maerics Donc, si je suivais votre réponse, un chèque nul comme le scénario ci - dessus, vous ne pas utiliser !=du tout, seule comparaison stricte, !==?
afsantos
@rynah: Je ne présume pas en savoir suffisamment sur la solution globale d'OP pour savoir si un test nul est approprié ou non, mais j'ai modifié pour mentionner le fait que l'utilisation de "typeof" est inutile.
maerics
@afsantos: en réalité, je ne pense pas que de nombreuses valeurs (aucune?) seront converties en valeurs nulles; cependant, il est recommandé d'utiliser la comparaison stricte ( ===) à moins que vous ne sachiez vraiment ce que vous faites et que vous souhaitiez une comparaison après la conversion ( ==).
maerics
1
@Izkata: supprimez toute bibliothèque qui tente de redéfinir undefined. De plus, Safari sur iPad ne le fera en aucun cas. Vous ne pouvez même pas delete window.undefined.
Ry-
10

Dans votre cas, utilisez data==null(qui est vrai UNIQUEMENT pour null et indéfini - sur la deuxième image, focus sur les lignes / colonnes null-undefined)

Ici vous avez tout ( src ):

si

entrez la description de l'image ici

== (sa négation ! = )

entrez la description de l'image ici

=== (sa négation ! == )

entrez la description de l'image ici

Kamil Kiełczewski
la source
8

Q: La fonction a été appelée sans argument, faisant ainsi des données une variable non définie et générant une erreur sur les données! = Null.

R: Oui, datasera défini sur indéfini. Voir section 10.5 Déclaration de liaison Instanciation de la spécification. Mais accéder à une valeur non définie ne génère pas d'erreur. Vous confondez probablement cela avec l'accès à une variable non déclarée en mode strict, ce qui génère une erreur.

Q: La fonction a été appelée spécifiquement avec null (ou non défini) comme argument, auquel cas data! = Null protège déjà le code interne, rendant && data! == undefined inutile.

Q: La fonction a été appelée avec un argument non nul, auquel cas elle passera trivialement les données! = Null et les données! == non définies.

R: Correct. Notez que les tests suivants sont équivalents:

data != null
data != undefined
data !== null && data !== undefined

Voir la section 11.9.3 L'algorithme de comparaison d'égalité abstraite et la section 11.9.6 L'algorithme de comparaison d'égalité stricte de la spécification.

nwellnhof
la source
Je ne confondais pas avec les variables non déclarées, je ne savais vraiment pas comment cela fonctionnait quand aucun argument n'était fourni. J'étais convaincu que datacela n'existerait pas du tout, au lieu d'être réglé undefined. J'apprécie la clarification, et ces références m'ont aidé à mieux comprendre comment fonctionnent les deux égalités.
afsantos
3

Je pense que tester des variables pour des valeurs auxquelles vous ne vous attendez pas n'est pas une bonne idée en général. Parce que le test est le vôtre, vous pouvez le considérer comme l'écriture d'une liste noire de valeurs interdites. Mais que faire si vous oubliez de lister toutes les valeurs interdites? Quelqu'un, même vous, peut déchiffrer votre code en passant une valeur inattendue. Donc, une approche plus appropriée est quelque chose comme la liste blanche - tester les variables uniquement pour les valeurs attendues, pas inattendues. Par exemple, si vous vous attendez à ce que la valeur des données soit une chaîne, au lieu de ceci:

function (data) {
  if (data != null && data !== undefined) {
    // some code here
    // but what if data === false?
    // or data === '' - empty string?
  }
}

faites quelque chose comme ça:

function (data) {
  if (typeof data === 'string' && data.length) {
    // consume string here, it is here for sure
    // cleaner, it is obvious what type you expect
    // safer, less error prone due to implicit coercion
  } 
}

la source
2

typeof foo === "undefined"est différent de foo === undefined, ne les confondez jamais. typeof foo === "undefined"est ce dont vous avez vraiment besoin. Utilisez également !==à la place de!=

Ainsi, la déclaration peut être écrite comme

function (data) {
  if (typeof data !== "undefined" && data !== null) {
    // some code here
  }
}

Éditer:

Vous ne pouvez pas utiliser foo === undefinedpour les variables non déclarées.

var t1;

if(typeof t1 === "undefined")
{
  alert("cp1");
}

if(t1 === undefined)
{
  alert("cp2");
}

if(typeof t2 === "undefined")
{
  alert("cp3");
}

if(t2 === undefined) // fails as t2 is never declared
{
  alert("cp4");
}

la source
1
D'accord, mais la variable est déclarée dans ce cas, alors quel est le problème?
Ry-
Personnellement, je trouve foo === undefineddangereux à utiliser. Cela fait échouer votre code pour la même condition que vous essayiez d'éviter.
Je parle de l'argument de la fonction en question. Voir aussi mon autre commentaire .
Ry-
1
Pourquoi ce vote est-il défavorable? La toute première phrase est une distinction correcte et importante !
Izkata
1
@Izkata: parce qu'il n'y a pas d'explication pour la déclaration initiale. foo === undefinedest parfaitement acceptable dans la situation du PO (en supposant qu'il undefinedn'a pas été annulé). La réponse ne parvient pas non plus à expliquer pourquoi !== devrait être utilisé à la place de !=.
Matt
1

La façon simple de faire votre test est:

function (data) {
    if (data) { // check if null, undefined, empty ...
        // some code here
    }
}
Kadiri
la source
5
Ce test n'est-il pas dépendant du contexte? Je veux dire, si le type attendu pour dataest une chaîne, ce test renvoie false sur les chaînes vides, ce qui peut, ou non, être approprié (la fonction peut vouloir traiter la chaîne vide d'une manière ou d'une autre).
afsantos
5
Sauf que si "data" a la valeur ""ou 0ou NaN(ou autres) le bloc "if" sera ignoré; ce qui peut ou non être l'intention d'OP.
maerics
Désolé @afsantos, je n'ai pas vu votre commentaire, si vous voulez obtenir false lorsque les données sont indéfinies, nulles ... sauf lorsque la date est vide, vous devrez créer un autre var toTest = data; avec un autre test après le premier comme: if (toTest == "") {// un peu de code ici}
Kadiri
-5
var a;
alert(a); //Value is undefined

var b = "Volvo"; 
alert(b); //Value is Volvo

var c = null;
alert(c); //Value is null
débordement
la source
4
Veuillez ajouter quelques explications sur ce que cela signifie.
Ry-
Cela ne veut pas vraiment vérifier pour null.
user4642212