Pourquoi y a-t-il une valeur «null» dans JavaScript?

116

En JavaScript, il y a deux valeurs qui disent essentiellement «je n'existe pas» - undefinedet null.

Une propriété à laquelle un programmeur n'a rien assigné le sera undefined, mais pour qu'une propriété devienne null, elle nulldoit lui être explicitement assignée.

J'ai pensé une fois qu'il y avait un besoin de nullparce que undefinedc'est une valeur primitive et nullun objet. Ce n'est pas, même si typeof nullcela donnera 'object': en fait, les deux sont des valeurs primitives - ce qui signifie que ni undefinedni nullne peut être retourné à partir d'une fonction de constructeur, car les deux seront convertis en un objet vide (il faut lancer une erreur pour proclamer l'échec des constructeurs).

Ils sont également tous deux évalués falsedans des contextes booléens. La seule vraie différence à laquelle je puisse penser est que l'un évalue à NaN, l'autre à 0dans des contextes numériques.

Alors pourquoi y a-t-il les deux undefinedet nullsi cela ne fait que confondre les programmeurs qui vérifient de manière incorrecte nulllorsqu'ils essaient de savoir si une propriété a été définie ou non?

Ce que j'aimerais savoir, c'est si quelqu'un a un exemple raisonnable où il est nécessaire d'utiliser nullce qui ne pourrait pas être exprimé en utilisant à la undefinedplace.

Ainsi, le consensus général semble être que cela undefinedsignifie «il n'y a pas de telle propriété» alors que nullsignifie «la propriété existe, mais n'a aucune valeur».

Je pourrais vivre avec cela si les implémentations JavaScript imposaient réellement ce comportement - mais undefinedc'est une valeur primitive parfaitement valide, donc elle peut facilement être attribuée à des propriétés existantes pour rompre ce contrat. Par conséquent, si vous voulez vous assurer qu'une propriété existe, vous devez utiliser l' inopérateur ou de hasOwnProperty()toute façon. Encore une fois: quelle est l'utilité pratique des valeurs séparées pour undefinedet null?

J'utilise en fait undefinedquand je veux annuler les valeurs de propriétés qui ne sont plus utilisées mais que je ne veux pas delete. Dois-je utiliser à la nullplace?

Christoph
la source
3
Pour répondre à votre dernière question: Non, vous ne devez pas définir les propriétés sur undefined.
Shog9
4
"undefined" est juste une variable dans la portée globale avec la valeur primitive "undefined". Il est possible de définir une autre valeur pour la variable: {undefined = "Hello"; alert (undefined);} Un moyen plus fiable de tester undefined: {if (typeof myvar === "undefined") alert ("undefined")}
certains
1
Voir la section 4.3.9 - 12 dans ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf pour undefined / null et 15.1.1.3 pour la variable "undefined" dans la portée globale.
certains
1
Vous devez soit supprimer un objet, soit le définir sur null si cela a plus de sens, mais pas sur indéfini.
certains
4
In JavaScript, there are two values which basically say 'I don't exist' - undefined and null.Non, undefineddit seulement ça.
Courses de légèreté en orbite le

Réponses:

78

La question n'est pas vraiment "pourquoi y a-t-il une valeur nulle dans JS" - il y a une valeur nulle d'une sorte dans la plupart des langages et elle est généralement considérée comme très utile.

La question est, "pourquoi y a-t-il une valeur indéfinie dans JS". Principaux endroits où il est utilisé:

  1. lorsque vous déclarez var x;mais ne lui assignez pas, xdétient undefined;
  2. lorsque votre fonction reçoit moins d'arguments qu'elle n'en déclare;
  3. lorsque vous accédez à une propriété d'objet inexistante.

nullaurait certainement fonctionné aussi bien pour (1) et (2) *. (3) devrait vraiment lancer une exception tout de suite, et le fait que ce ne soit pas le cas, au lieu de renvoyer cet étrange undefinedqui échouera plus tard, est une grande source de difficultés de débogage.

*: vous pouvez également affirmer que (2) devrait lever une exception, mais vous devrez alors fournir un meilleur mécanisme plus explicite pour les arguments par défaut / variables.

Cependant, à l'origine, JavaScript n'avait pas d'exceptions, ni aucun moyen de demander à un objet s'il avait un membre sous un certain nom - le seul moyen était (et est toujours) d'accéder au membre et de voir ce que vous obtenez. Étant donné que cela nullavait déjà un objectif et que vous souhaitiez peut-être y attribuer un membre, une valeur hors bande différente était requise. Donc, nous avons undefined, c'est problématique comme vous le faites remarquer, et c'est une autre excellente «fonctionnalité» JavaScript dont nous ne pourrons jamais nous débarrasser.

J'utilise en fait undefined lorsque je souhaite annuler la définition des valeurs de propriétés qui ne sont plus utilisées mais que je ne souhaite pas supprimer. Dois-je utiliser null à la place?

Oui. Conserver undefinedcomme valeur spéciale pour signaler quand d'autres langages peuvent lever une exception à la place.

nullest généralement mieux, sauf sur certaines interfaces IE DOM où la définition de quelque chose sur nullpeut vous donner une erreur. Souvent, dans ce cas, la définition de la chaîne vide a tendance à fonctionner.

bobince
la source
10
Les Args sont extensibles. Vous pouvez en ajouter autant que vous le souhaitez et une fonction pourrait potentiellement les parcourir et les utiliser toutes. Les objets peuvent se voir attribuer une nouvelle propriété à tout moment. Ce sont deux fonctionnalités puissantes, mais je soupçonne que le fait de lancer des exceptions comme vous le préférez entraînerait beaucoup de surcharge. OMI, ça vaut le compromis. Je passe beaucoup moins de temps à vérifier l'existence dans JS que je ne le fais typiquement dans des paradigmes de langage plus stricts.
Erik Reppen
C'est drôle comment la réponse acceptée à une question commence par "ce n'est pas vraiment la question ..."
Phillip
@bobince les premières versions de JS n'avaient-elles pas l' inopérateur ou hasOwnProperty? Parce qu'ils sont bien plus sûrs que obj.hello !== undefinedpour vérifier si une propriété existe sur un objet.
Andy
Peu importe, j'ai répondu à ma propre question. Selon MDN, ils ont tous deux été introduits dans ES3.
Andy
37

Mieux décrit ici , mais en résumé:

undefined est l'absence de type et de valeur, et null est l'absence de valeur.

De plus, si vous faites de simples comparaisons '==', vous avez raison, elles sortent de la même manière. Mais essayez ===, qui compare le type et la valeur, et vous remarquerez la différence.

Eddie Parker
la source
1
Je sais que null !== undefined- ma question était pourquoi il y avait un besoin de deux choses qui expriment le même concept sémantique; aussi, votre lien mentionne que `` null est un objet '' - c'est faux, c'est un primitif ...
Christoph
2
Ce n'est pas le même concept sémantique. Pour moi au moins, il existe une différence significative entre une propriété à laquelle une valeur nulle est attribuée et une propriété qui n'existe pas.
Daniel Schaffer
Mais c'est juste ça, ce n'est pas le même concept sémantique. Null est contraint lors de l'utilisation de == à impliquer la même chose, par commodité pour le programmeur.
Eddie Parker
1
@EricElliott: typeofmensonges - lisez les spécifications ou essayez de revenir nulld'un constructeur
Christoph
5
@EricElliott: la valeur de retour des constructeurs n'a rien à voir avec falsy-ness, mais avec object-ness: si la valeur de retour est un objet, renvoyez-le; si c'est un primitif comme nullou 42, ignorez la valeur de retour et renvoyez l'objet nouvellement créé à la place
Christoph
17

Je ne pense pas qu'il y ait de raison d'avoir les deux nullet undefined, parce que la seule raison que beaucoup de gens ont suggérée (" undefinedsignifie qu'il n'y a pas de telle variable / propriété") n'est pas valide, du moins en JavaScript. undefinedne peut pas vous dire si la variable / propriété existe ou non.

console.log(foo);               // "ReferenceError: foo is not defined"
                                // foo does not exist
var foo;
console.log(foo);               // "undefined", a different response
console.log(foo === undefined); // "true", but it does exist

var obj = {};
console.log(obj.hasOwnProperty("foo")); // "false", no such property
obj.foo = undefined;
console.log(obj.hasOwnProperty("foo")); // "true", it exists and has the value "undefined"
console.log(obj.foo === undefined);     // "true", but it does exist

obj.bar = "delete me";
obj.bar = undefined;
console.log(obj.hasOwnProperty("bar")); // "true", not actually deleted
delete obj.bar;
console.log(obj.hasOwnProperty("bar")); // "false", deleted

Comme vous pouvez le voir, la vérification foo === undefinedne vous dit pas s'il fooexiste et le paramètre obj.bar = undefinedne supprime pas réellement bar.

Ce peut être l'intention originale de l'auteur JavaScript qui undefineddevrait représenter la «non-existence». Cependant, la mise en œuvre ne s'est pas déroulée de cette façon.

Lei Zhao
la source
1
Remplacez undefinedpar nulldans vos exemples de code ci-dessus, et les réponses sont toutes les mêmes. Je ne sais pas comment cela répond à la question. S'agissait-il d'un commentaire sur la réponse de quelqu'un d'autre?
Eric Elliott
1
@EricElliott Ma réponse à la question est qu'il n'y a aucune raison d'avoir les deux nullet undefined, parce que la seule raison que beaucoup de gens ont suggérée n'est pas valide.
Lei Zhao
Vous devriez modifier votre réponse et le dire. J'aurais pu voter si vous aviez donné cette réponse. =)
Eric Elliott
@EricElliott Je pense que vous avez raison. J'ai édité ma réponse. Merci!
Lei Zhao
3
Cet exemple montre en fait que si vous n'avez pas affecté de variable, elle renvoie undefined. Mais si vous l'avez assigné undefined, ce n'est pas réellement undefined- il a été défini avec undefinedet y fait référence. La seule différence entre undefinedet nullest leur utilisation et leur objectif historique. Ils sont tous les deux atomiques.
Aleksej Komarov
6

Il est tout à fait possible d'avoir besoin des deux. Par exemple, si vous interrogez WMI, il est tout à fait possible qu'une classe renvoie des propriétés qui ont une valeur nulle. Ils sont définis, ils sont simplement nuls à ce moment-là.

EBGreen
la source
6

Je pense que votre conclusion selon laquelle JavaScript définit undefinedcomme "une telle propriété n'existe pas" et nullcomme "la propriété n'a aucune valeur" est parfaitement correcte. Et dans un langage aussi dynamique que JavaScript, c'est une distinction très importante. L'utilisation du typage canard signifie que nous devons être capables de faire la différence entre une propriété qui n'existe pas et qui n'a pas de valeur. C'est notre principal moyen de dériver des informations de type. dans un langage de typage statique, il existe une distinction nette entre un champ nul et un champ inexistant. En JavaScript, ce n'est pas différent. Cependant, il est vérifié à l'exécution et peut être modifié jusqu'à ce moment-là.

Je vais devoir convenir que la mise en œuvre est étrange car la distinction est souvent floue. Cependant, je pense qu'en JavaScript, la distinction est importante. Et pouvoir attribuer undefinedest essentiel.

Je me souviens avoir lu un article de blog il y a quelque temps sur un RPG en ligne écrit en JavaScript. Il a utilisé des exemples où les objets ont été créés comme des copies d'instances existantes plutôt que des prototypes (classes, fonctions, etc.), puis modifiés. Cela m'a vraiment fait comprendre à quel point cela undefinedpouvait être puissant lors de la modification d'objets existants, mais je ne me souviens pas qui l'a écrit.

Jack Ryan
la source
Pourriez-vous s'il vous plaît partager ce RPG?
Michael le
3

Sémantiquement, ils signifient des choses différentes. Le type null a exactement une valeur dans son domaine, null et une propriété peut se voir attribuer cette valeur spécifique. Undefined représente une absence distincte de toute valeur attribuée.

AnthonyWJones
la source
1
mais vous pouvez utiliser undefinedtrès bien pour attribuer des propriétés, donc ce contrat (ne revient que undfineds'il n'y a pas de propriété de ce type) peut facilement être rompu par le programmeur ...
Christoph
2
Vous pouvez , mais vous ne devriez certainement pas. Undefined est utilisé comme une forme d'exception très basique / simpliste en JavaScript - ne l'utilisez pas comme valeur et attribuez-la à une propriété! C'est fou.
rfunduk
3

En tant que programmeur Java, je vois une énorme différence entre undefined et null. Coder JavaScript, pas tellement, car JavaScript n'est pas fortement typé et les différences entre undefined et null sont estompées par les conversions automatiques qui sont fréquemment effectuées au moment de l'exécution. BTW, je profite fréquemment de ces conversions; ils rendent mon code JS plus compact et plus lisible.

Pour répondre à votre question, indéfini signifie qu'une valeur n'a jamais été définie. En pratique, cela indique généralement un bogue. Si yourObject.property n'est pas défini, cela signifie que vous n'avez pas défini la propriété pour une raison quelconque, ou que je recherche quelque chose qui n'existe pas du tout. C'est un vrai problème lorsque l'on travaille sur un projet avec plus d'un codeur.

null signifie que "aucune valeur" n'a été explicitement définie. En pratique, vous me dites quelque chose sur la propriété, peut-être qu'elle n'est pas utilisée dans ce contexte, ou qu'une valeur doit encore être déterminée.

En Java, les tentatives d'accès à un champ non défini entraîneront toujours une exception. En fait, le compilateur peut être conçu pour vous en avertir dans votre code.

Steve11235
la source
0

Essayez cet exemple:

<html>
<head>
    <script type="text/javascript">
        function ShowObjProperties(obj) {
            var property, propCollection = "";

            for(property in obj) {
                propCollection += (property + ": " + obj[property] + "\n");
            }

            alert(propCollection);
        }

        var obj = {
            userid: 3,
            name: 'me!',
            speak: function() { alert('Hi! My name is ' + this.name + ' and my ID is ' + this.userid + '.'); }
        }

        //Shows all properties
        ShowObjProperties(obj);

        //The Speak function is no longer in the list!
        delete obj.speak;
        alert(typeof obj.speak);
        ShowObjProperties(obj);

        //The UserID is still listed, it just has no value!
        obj.userid = null;
        ShowObjProperties(obj);
    </script>
</head>
<body>

</body>
</html>

Je pense qu'il y a une utilisation très réelle de 2 types différents ici.

En voie de disparitionMassa
la source
Et dans les prototypes, je pense, est un membre nul ou tout simplement indéfini.
Kev
mais cela ne fonctionne que tant que personne n'essaye de le casser - si je règle obj.userid = undefined, ça échouera - voir la dernière modification de ma question
Christoph
0

Il s'agit en fait de la nature dynamique des javascripts.

Les choses peuvent être indéfinies afin de pouvoir être ajoutées ultérieurement. C'est sans doute pourquoi javascript est si puissant et extensible.

Rob Stevenson-Leggett
la source
et cela est pertinent pour ma question de quelle manière?
Christoph
2
C'est pertinent car il répond à votre question. «null» est une sorte de «singleton» qui signifie «n'a pas de valeur». «indéfini» vous dit que quelque chose est ... choquant, je sais ... non défini. Ce sont des choses complètement différentes.
rfunduk
0

c'est une fonctionnalité de langage importante si vous enveloppez votre programme autour du paradigme événementiel de javascript.

// a key exists as a placeholder for something
if(obj[name] === null) 
// no key exists int eh hashtable that is in this object
if(obj[name] === undefined)

ceci est très utile si vous avez affaire à un ensemble de données qui a besoin d'une valeur pour représenter «rien» pour indiquer une action différente de l'utilisation de «rien» pour indiquer l'action par défaut.

filter_func_pt = {
  date:function(d){ return Math.round(d.getTime()/1000);},
  user: null,
}

function transform(obj){
    var ret = {};
    for( var prop in obj){
       var f = filter_func_pt[prop];
       if(f)
          ret[prop] = f(obj);
       else if(filter_func_pt[prop] === null)
         continue;
       else
         ret[prop] == obj;
    }
  return ret;
}

var a = {
   date: new Date(),
   user: 'sam'
   votes: [23, 41, 55] 
};

var b = transform(a);

/* b = {
 *    date: 1298582417
 *    votes: [23, 41, 55]
 * }
 */

dans le code ci-dessus, le mot clé null et le serveur non défini à des fins très claires et différentes. la recherche qui ne se trouve pas dans l'objet filter_func_pt qui retourne undefined signifie ajouter la propriété à l'objet de retour tel quel , alors qu'une valeur nulle indique que la valeur doit être retenue, et non ajoutée, et la présence d'une valeur vraie dans ce case représente une fonction utilisée pour transformer la valeur avant de l'ajouter à l' objet ret .

Corbeau de feu
la source
Cet exemple est artificiel et un peu absurde. Null ne clarifie pas du tout votre intention, mais la masque. Vous auriez pu utiliser une chaîne plus explicite pour clarifier la signification. Par exemple, «retenir» ou «supprimer» et vous pouvez également être plus explicite sur le type de fonction et vérifier réellement la présence d'une fonction.
Eric Elliott
0

nul est beau

comme tous les autres types de Live Script.

cite: En JavaScript, il y a deux valeurs qui disent essentiellement «je n'existe pas» - indéfini et nul.

Pourquoi voudriez-vous dire des choses incorrectes?!

"null" est un "objet vide" tout comme "0" est un "nombre vide" . 0, n'est rien - pourtant, il existe en tant que type d'une chose numérique. null est bien sûr également vide mais "c'est" et c'est une chose bien définie d'un type d'objet .

Il est courant de parler de ces choses comme de «types», alors qu'ils ne le sont pas. En fait, ce sont des «catégories». Mais c'est fini maintenant.

Donc, je vais vous en tenir à cela pour dire que "null" est un type d'objet sans sorte. Et "nul" dit "j'existe beaucoup [!], Mais je n'ai pas de contenu de mon genre".

Alors qu'undefined n'a pas à la fois le Type et le Kind où indéfini se trouve être également sa définition de Type. Un type non défini d'un type devient sa typologie distinctive. Une sorte de question ["rien" n'existe-t-il et comment définissez-vous "rien"?].

cite: undefined ni null peuvent être retournés à partir d'une fonction constructeur, car les deux seront convertis en un objet vide

Vous avez réussi à dire une fois de plus une chose incorrecte. Bien sûr que non, le "non défini" n'est pas un objet, c'est un simple jeton que nous, les humains, comprenons; mais contrairement à ce null est - et cela vous dit que: son Type est correct, mais le Kind que vous recherchez n'est pas contenu dedans, ou du moins -pas pour le moment. Venez nous rendre visite plus tard lorsque nous y placerons \ attribuer un objet \.

citer: La seule vraie différence à laquelle je peux penser est que l'un évalue à NaN, l'autre à 0 dans des contextes numériques.

Cela fait tout l'intérêt de leur distinction fondamentale, comme mentionné: undefined est un simple jeton et comme il est composé du même matériel `` génétique '' que ses parents éloignés: des chaînes, l'opération [+ undefined] le convertira en NaN, de la même manière null se transforme bien sûr en un type correct 0 \ Number à la place, et contrairement à undefined qui se transforme en une chaîne (! Qui n'est pas vide!) Et c'est exactement pourquoi il donne NaN à la place. Où: + undefined >> + "undefined" >> NaN. Puisque le contexte numérique attend une valeur explicite.

Alors que le contexte booléen attend une référence - ne trouve rien à convertir et renvoie «faux».

Coupons maintenant ...

cite: Encore une fois: quelle est l'utilité pratique des valeurs séparées pour undefined et null?

J'essaierai de vous donner seulement deux exemples empiriques et j'espère suffire

oElement.onclick >> null

// signifie que la propriété existe; sa valeur attendue est de Type: Object , et que oElement prend en charge l'événement "onclick"!

oElement.innerText >> ""

// signifie - la propriété existe; sa valeur attendue est de Type: String , ce qui signifie que oElement prend en charge la propriété "innerText".

dans les deux cas -si vous recevez "undefined" cela signifie que la propriété n'existe pas; n'est pas pris en charge ou a une mauvaise implémentation (ua vendor).

Restez gelé et amusez-vous.

Bill le lézard
la source
Ne vandalisez pas vos messages, enée. Supprimez-les (en utilisant le bouton Supprimer juste au-dessus de ce commentaire) si vous souhaitez supprimer votre contribution.
Michael Petrotta
il n'y a pas de bouton de suppression - mais au cas où vous le voyez, cliquez dessus!
0

après avoir lu une discussion incroyable sur undefined vs null, une petite recherche sur google m'a conduit à Mozilla Documentations https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null il est mentionné - null est souvent récupéré dans un endroit où un objet peut être attendu mais aucun objet n'est pertinent.

N'est pas similaire au modèle d'objet nul https://en.wikipedia.org/wiki/Null_object_pattern

Donc, je suppose que cela a du sens d'avoir un type de données Null.

Documentation également mentionnée comme typeof null // "object" (pas "null" pour des raisons héritées)

Je ne sais pas quelles sont les raisons héritées

Vishal Bhandare
la source