Warum gibt es in JavaScript einen Nullwert?


115

In JavaScript gibt es zwei Werte, die im Grunde sagen: "Ich existiere nicht" - undefinedund null.

Eine Eigenschaft, der ein Programmierer nichts zugewiesen hat , muss explizit zugewiesen werden, damit undefinedeine Eigenschaft wird .nullnull

Ich dachte einmal, dass es einen Bedarf gibt, nullweil undefinedes sich um einen primitiven Wert und nullein Objekt handelt. Es ist nicht, auch wenn typeof nullergeben wird 'object': Eigentlich beide primitive Werte sind - was bedeutet weder , undefinednoch nullkann von einer Konstruktor - Funktion zurückgegeben werden, da beide in ein leeres Objekt umgewandelt wird (man hat einen Fehler proclaim Fehler in Konstrukteuren zu werfen).

Sie bewerten beide auch falsein booleschen Kontexten. Der einzige wirkliche Unterschied, den ich mir vorstellen kann, ist, dass einer in numerischen Kontexten bewertet NaN, der andere 0.

Warum gibt es also beides undefinedund nullwenn dies nur Programmierer verwirrt, die fälschlicherweise nachsehen null, ob eine Eigenschaft festgelegt wurde oder nicht?

Was ich gerne wissen würde, ist, ob jemand ein vernünftiges Beispiel hat, bei dem es notwendig ist, etwas zu verwenden, nulldas undefinedstattdessen nicht ausgedrückt werden kann .

Der allgemeine Konsens scheint also zu sein, dass undefined"es gibt keine solche Eigenschaft" nullbedeutet, während "die Eigenschaft existiert, aber keinen Wert hat" bedeutet.

Ich könnte damit leben, wenn JavaScript-Implementierungen dieses Verhalten tatsächlich erzwingen würden - aber es undefinedist ein vollkommen gültiger primitiver Wert, sodass er leicht vorhandenen Eigenschaften zugewiesen werden kann, um diesen Vertrag zu brechen. Wenn Sie also sicherstellen möchten, dass eine Eigenschaft vorhanden ist, müssen Sie den inOperator oder einen anderen verwenden hasOwnProperty(). Also noch einmal: Was ist die praktische Verwendung für separate Werte für undefinedund null?

Ich verwende es tatsächlich, undefinedwenn ich die Werte von Eigenschaften deaktivieren möchte, die nicht mehr verwendet werden, die ich aber nicht möchte delete. Soll ich nullstattdessen verwenden?


3
So beantworten Sie Ihre letzte Frage: Nein, Sie sollten keine Eigenschaften festlegen undefined.
Shog9

4
"undefined" ist nur eine Variable im globalen Bereich mit dem primitiven Wert "undefined". Es ist möglich, einen anderen Wert für die Variable zu definieren: {undefined = "Hello"; alert (undefined);} Ein zuverlässigerer Weg, um auf undefined zu testen: {if (typeof myvar === "undefined") alert ("undefined")}
einige

1
Siehe Abschnitt 4.3.9 - 12 in ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf für undefined / null und 15.1.1.3 für die Variable "undefined" im globalen Bereich.
einige

1
Sie sollten ein Objekt entweder löschen oder auf null setzen, wenn dies sinnvoller ist, aber nicht auf undefiniert.
einige

4
In JavaScript, there are two values which basically say 'I don't exist' - undefined and null.Nein, undefinedsagt nur das.
Leichtigkeitsrennen im Orbit

Antworten:


78

Die Frage ist nicht wirklich "Warum gibt es in JS einen Nullwert?" - In den meisten Sprachen gibt es einen Nullwert, der allgemein als sehr nützlich angesehen wird.

Die Frage ist: "Warum gibt es in JS einen undefinierten Wert?" Wichtige Orte, an denen es verwendet wird:

  1. Wenn Sie deklarieren, var x;aber nicht zuweisen, xgilt undefiniert.
  2. wenn Ihre Funktion weniger Argumente erhält als deklariert;
  3. wenn Sie auf eine nicht vorhandene Objekteigenschaft zugreifen.

nullhätte sicherlich genauso gut für (1) und (2) * funktioniert. (3) sollte wirklich sofort eine Ausnahme auslösen, und die Tatsache, dass dies nicht der Fall ist, anstatt diese seltsame undefined, die später fehlschlagen wird, zurückzugeben, ist eine große Quelle von Debugging-Schwierigkeiten.

*: Sie könnten auch argumentieren, dass (2) eine Ausnahme auslösen sollte, aber dann müssten Sie einen besseren, expliziteren Mechanismus für Standard- / Variablenargumente bereitstellen.

Allerdings hatte JavaScript ursprünglich keine Ausnahmen oder eine Möglichkeit, ein Objekt zu fragen, ob es ein Mitglied unter einem bestimmten Namen hatte - die einzige Möglichkeit war (und ist es manchmal immer noch), auf das Mitglied zuzugreifen und zu sehen, was Sie erhalten. Da dies nullbereits einen Zweck hatte und Sie möglicherweise ein Mitglied festlegen möchten, war ein anderer Out-of-Band-Wert erforderlich. Wir haben also undefined, es ist problematisch, wie Sie betonen, und es ist eine weitere großartige JavaScript-Funktion, die wir niemals loswerden können.

Ich verwende eigentlich undefined, wenn ich die Werte von Eigenschaften deaktivieren möchte, die nicht mehr verwendet werden, die ich aber nicht löschen möchte. Soll ich stattdessen null verwenden?

Ja. Behalten Sie undefinedals speziellen Wert für die Signalisierung bei, wenn andere Sprachen stattdessen eine Ausnahme auslösen könnten.

nullist im Allgemeinen besser, außer bei einigen IE-DOM-Schnittstellen, bei denen das Festlegen von etwas zu nulleinem Fehler führen kann. In diesem Fall funktioniert die Einstellung auf die leere Zeichenfolge häufig.


10
Args sind erweiterbar. Sie können so viele hinzufügen, wie Sie möchten, und eine Funktion kann möglicherweise alle durchlaufen und nutzen. Objekten kann jederzeit eine neue Eigenschaft zugewiesen werden. Dies sind beide leistungsstarke Funktionen, aber ich vermute, dass das Auslösen von Ausnahmen, wie Sie es bevorzugen, viel Aufwand bedeuten würde. IMO, es ist den Kompromiss wert. Ich verbringe viel weniger Zeit damit, in JS nach Existenz zu suchen, als normalerweise mit strengeren Sprachparadigmen.
Erik Reppen

Lustig, wie die akzeptierte Antwort auf eine Frage mit "das ist nicht wirklich die Frage ..." beginnt
Phillip

@bobince hatten frühe Versionen von JS nicht den inOperator oder hasOwnProperty? Weil sie viel sicherer sind als die obj.hello !== undefinedÜberprüfung, ob eine Eigenschaft für ein Objekt vorhanden ist.
Andy

Egal, ich beantwortete meine eigene Frage. Laut MDN wurden beide in ES3 eingeführt.
Andy

37

Am besten hier beschrieben , aber zusammenfassend:

undefiniert ist das Fehlen eines Typs und Werts, und null ist das Fehlen eines Wertes.

Wenn Sie einfache '==' Vergleiche durchführen, haben Sie Recht, sie kommen gleich heraus. Aber versuchen Sie ===, das sowohl Typ als auch Wert vergleicht, und Sie werden den Unterschied bemerken.


1
Ich weiß das null !== undefined- meine Frage war, warum zwei Dinge benötigt wurden, die dasselbe semantische Konzept ausdrücken; Außerdem erwähnt Ihr Link, dass 'null ein Objekt ist' - das ist falsch, es ist ein Primitiv ...
Christoph

2
Sie sind nicht dasselbe semantische Konzept. Zumindest für mich gibt es einen signifikanten Unterschied zwischen einer Eigenschaft, der ein Nullwert zugewiesen wurde, und einer Eigenschaft, die nicht vorhanden ist.
Daniel Schaffer

Aber das ist es nur, sie sind nicht das gleiche semantische Konzept. Null wird gezwungen, wenn == verwendet wird, um dasselbe zu implizieren, um es dem Programmierer zu erleichtern.
Eddie Parker

1
@ EricElliott: typeofLügen - lesen Sie die Spezifikation oder versuchen Sie, nullvon einem Konstruktor zurückzukehren
Christoph

5
@EricElliott: Der Rückgabewert von Konstruktoren hat nichts mit Falschheit zu tun, sondern mit Objekthaftigkeit: Wenn der Rückgabewert ein Objekt ist, geben Sie das zurück. Wenn es sich um ein primitives Objekt wie nulloder handelt 42, verwerfen Sie den Rückgabewert und geben Sie stattdessen das neu erstellte Objekt zurück
Christoph,

17

Ich glaube nicht, dass es einen Grund gibt, beides zu haben, nullund undefinedweil der einzige Grund, den viele Leute vorgeschlagen haben (" undefinedbedeutet, dass es keine solche Variable / Eigenschaft gibt"), zumindest in JavaScript nicht gültig ist. undefinedkann Ihnen nicht sagen, ob die Variable / Eigenschaft existiert oder nicht.

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

Wie Sie sehen können, zeigt die Überprüfung foo === undefinednicht an, ob sie foovorhanden ist, und die Einstellung obj.bar = undefinedwird nicht tatsächlich gelöscht bar.

Es kann die ursprüngliche Absicht des JavaScript-Autors sein, undefineddie "Nichtexistenz" darstellen sollte. Die Implementierung verlief jedoch nicht so.


1
Ersetzen Sie undefinedmit nullin Ihrem obigen Beispiel - Code und die Antworten sind alle gleich. Ich bin mir nicht sicher, wie dies die Frage beantwortet. War dies als Kommentar zur Antwort eines anderen gedacht?
Eric Elliott

1
@EricElliott Meine Antwort auf die Frage ist, dass es keinen Grund gibt, beides zu haben, nullund undefinedweil der einzige Grund, den viele Leute vorgeschlagen haben, nicht gültig ist.
Lei Zhao

Sie sollten Ihre Antwort bearbeiten und das tatsächlich sagen. Ich hätte vielleicht gestimmt, wenn Sie diese Antwort gegeben hätten. =)
Eric Elliott

@ EricElliott Ich denke du hast recht. Ich habe meine Antwort bearbeitet. Vielen Dank!
Lei Zhao

3
Dieses Beispiel zeigt tatsächlich, dass eine Variable zurückgegeben wird, wenn Sie sie nicht zugewiesen haben undefined. Aber wenn Sie es zugewiesen undefinedhaben, ist es nicht wirklich undefined- es wurde mit definiert undefinedund hat einen Verweis darauf. Der einzige Unterschied zwischen undefinedund nullist ihre Verwendung und ihr historischer Zweck. Sie sind beide atomar.
Aleksej Komarov

6

Es ist durchaus möglich, beides zu brauchen. Wenn Sie beispielsweise WMI abfragen, ist es durchaus möglich, dass Klassenrückgabeeigenschaften einen Nullwert haben. Sie sind definiert, sie halten gerade null.


6

Ich denke, dass Ihre Schlussfolgerung, die JavaScript undefinedals "es gibt keine solche Eigenschaft" und nullals "die Eigenschaft hat keinen Wert" definiert, vollkommen richtig ist. Und in einer so dynamischen Sprache wie JavaScript ist dies eine sehr wichtige Unterscheidung. Die Verwendung der Ententypisierung bedeutet, dass wir in der Lage sein müssen, zwischen einer Eigenschaft, die nicht existiert und keinen Wert hat, zu unterscheiden. Es ist unser primäres Mittel, um Typinformationen abzuleiten. In einer statisch typisierten Sprache gibt es einen eindeutigen Unterschied zwischen einem Feld, das null ist, und einem Feld, das nicht existiert. In JavaScript ist dies nicht anders. Es wird jedoch zur Laufzeit überprüft und kann bis zu diesem Zeitpunkt geändert werden.

Ich muss zustimmen, dass die Implementierung seltsam ist, da die Unterscheidung oft verschwimmt. Ich denke jedoch, dass in JavaScript die Unterscheidung wichtig ist. Und in der Lage zu sein, undefinedist wichtig.

Ich erinnere mich, dass ich vor einiger Zeit einen Blog-Beitrag über ein in JavaScript geschriebenes Online-Rollenspiel gelesen habe. Es wurden Beispiele verwendet, bei denen Objekte als Kopien vorhandener Instanzen und nicht als Prototypen (Klassen, Funktionen usw.) erstellt und anschließend geändert wurden. Dadurch habe ich wirklich verstanden, wie mächtig das undefinedsein kann, wenn vorhandene Objekte geändert werden, aber ich kann mich nicht erinnern, wer es geschrieben hat.


Könnten Sie bitte dieses Rollenspiel teilen?
Michael

3

Semantisch bedeuten sie verschiedene Dinge. Der Typ null hat genau einen Wert in seiner Domäne, null, und einer Eigenschaft kann dieser spezifische Wert zugewiesen werden. Undefiniert bedeutet einen deutlichen Mangel an zugewiesenem Wert.


1
Sie können jedoch problemlos undefinedObjekte zuweisen, sodass dieser Vertrag (nur zurückgeben, undfinedwenn keine solche Eigenschaft vorhanden ist) vom Programmierer leicht gebrochen werden kann ...
Christoph

2
Sie können , aber Sie sollten auf keinen Fall nicht. Undefiniert wird in JavaScript als sehr einfache / vereinfachte Ausnahmeform verwendet - verwenden Sie es nicht als Wert und weisen Sie es einer Eigenschaft zu! Das ist ein verrückter Mann.
Rfunduk

3

Als Java-Programmierer sehe ich einen großen Unterschied zwischen undefiniert und null. Codierung von JavaScript nicht so sehr, da JavaScript nicht stark typisiert ist und die Unterschiede zwischen undefiniert und null durch die automatischen Konvertierungen verwischt werden, die häufig zur Laufzeit ausgeführt werden. Übrigens nutze ich diese Konvertierungen häufig. Sie machen meinen JS-Code kompakter und lesbarer.

Um Ihre Frage zu beantworten, bedeutet undefiniert, dass niemals ein Wert festgelegt wurde. In der Praxis deutet dies im Allgemeinen auf einen Fehler hin. Wenn yourObject.property undefiniert ist, bedeutet dies, dass Sie die Eigenschaft aus irgendeinem Grund nicht festgelegt haben oder ich nach etwas suche, das überhaupt nicht vorhanden ist. Dies ist ein echtes Problem, wenn Sie an einem Projekt mit mehr als einem Codierer arbeiten.

null bedeutet, dass "kein Wert" explizit festgelegt wurde. In der Praxis erzählen Sie mir etwas über die Immobilie, vielleicht, dass sie in diesem Zusammenhang nicht verwendet wird oder dass ein Wert noch ermittelt werden muss.

In Java führen Versuche, auf ein undefiniertes Feld zuzugreifen, immer zu einer Ausnahme. Tatsächlich kann der Compiler dazu gebracht werden, Sie in Ihrem Code darüber zu warnen.


0

Versuchen Sie dieses Beispiel:

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

Ich denke, dass es hier eine sehr reale Verwendung für 2 verschiedene Typen gibt.


Und in Prototypen denke ich, ist ein Mitglied null oder nur undefiniert.
Kev

Dies funktioniert jedoch nur, solange niemand versucht, es zu brechen. Wenn ich es einstelle obj.userid = undefined, schlägt es fehl. Siehe die letzte Änderung meiner Frage
Christoph,

0

Worauf es ankommt, ist die dynamische Natur von Javascripts.

Dinge können undefiniert sein, damit sie zu einem späteren Zeitpunkt hinzugefügt werden können. Dies ist wohl der Grund, warum Javascript so leistungsfähig und erweiterbar ist.


und wie ist das für meine frage relevant?
Christoph

2
Es ist relevant, weil es Ihre Frage beantwortet. 'null' ist eine Art 'Singleton', was bedeutet 'hat keinen Wert'. 'undefined' sagt dir, dass etwas ... schockierend ist, ich weiß ... nicht definiert. Das sind ganz andere Dinge.
Rfunduk

0

Es ist eine wichtige Sprachfunktion, wenn Sie Ihr Programm um das ereignisreiche Paradigma von Javascript wickeln.

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

Dies ist sehr nützlich, wenn Sie mit einer Reihe von Daten arbeiten, die einen Wert benötigen, der "nichts" darstellt, um eine Aktion anzuzeigen, die sich von der Verwendung von "nichts" zur Angabe der Standardaktion unterscheidet.

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]
 * }
 */

Im obigen Code sind das Schlüsselwort null und der undefinierte Server sehr klar und dienen unterschiedlichen Zwecken. Die Suche, die nicht im filter_func_pt-Objekt gefunden wird, das undefiniert zurückgibt, bedeutet, dass die Eigenschaft dem Rückgabeobjekt unverändert hinzugefügt wird, während ein Nullwert angibt, dass der Wert zurückgehalten und nicht hinzugefügt werden soll, und dass ein wahrer Wert darin vorhanden ist case stellt eine Funktion dar, mit der der Wert transformiert wird, bevor er dem ret- Objekt hinzugefügt wird.


Dieses Beispiel ist erfunden und etwas unsinnig. Null klärt Ihre Absicht überhaupt nicht - vielmehr maskiert es sie. Sie hätten eine explizitere Zeichenfolge verwenden können, um die Bedeutung zu verdeutlichen. Zum Beispiel 'Zurückhalten' oder 'Entfernen', und dann können Sie auch den Funktionstyp genauer erläutern und tatsächlich prüfen, ob eine Funktion vorhanden ist.
Eric Elliott

0

null ist schön

wie alle anderen Arten von Live-Skripten.

Zitieren: In JavaScript gibt es zwei Werte, die im Grunde genommen "Ich existiere nicht" sagen - undefiniert und null.

Warum willst du falsche Dinge sagen?!

"null" ist "leeres Objekt", genau wie "0" eine "leere Zahl" ist . 0, ist nichts - aber es existiert als Typ einer Zahl. null ist natürlich auch leer, aber "es ist" und es ist eine gut definierte Sache von einem Objekttyps .

Es ist üblich, von diesen Dingen als "Typen" zu sprechen, wenn sie es nicht sind. In der Tat sind sie "Kategorien". Aber das ist jetzt vorbei.

Bleiben Sie also dabei und sagen Sie, dass "null" ein Objekttyp ohne Art ist. Und "null" sagt "Ich existiere sehr viel [!], Aber ich habe keinen Inhalt meiner Art".

Während undefiniert sowohl der Typ als auch die Art fehlt, wo undefiniert zufällig auch seine Typdefinition ist. Ein undefinierter Typ eines Typs wird zu seiner charakteristischen Typologie. Eine Art [existiert "nichts" und wie definieren Sie "nichts"?] Frage.

cite: undefined noch null können von einer Konstruktorfunktion zurückgegeben werden, da beide in ein leeres Objekt konvertiert werden

Sie haben es geschafft, noch einmal etwas Falsches zu sagen. Natürlich nicht, das "Undefinierte" ist kein Objekt, es ist ein einfaches Zeichen, das wir Menschen verstehen; aber im Gegensatz zu dieser Null ist - und es sagt Ihnen Folgendes: Sein Typ ist korrekt, aber die Art, nach der Sie suchen, ist nicht darin enthalten oder zumindest - zu diesem Zeitpunkt nicht. Besuchen Sie uns später, wenn wir ihm ein Objekt zuweisen.

Zitieren: Der einzige wirkliche Unterschied, den ich mir vorstellen kann, ist, dass einer NaN und der andere in numerischen Kontexten 0 ergibt.

Das macht den Kern ihrer Kernunterscheidung aus, wie erwähnt: undefined ist ein einfaches Zeichen, und da es aus demselben „genetischen“ Material besteht wie seine entfernten Verwandten: Strings, wird die [+ undefined] -Operation es in duck-konvertieren NaN, ähnlich null, verwandelt sich natürlich stattdessen in eine korrekte Art 0 \ Number, und im Gegensatz zu undefined verwandelt sich dies in einen String (!, Der nicht leer ist!), Und genau das ergibt es NaN stattdessen . Wobei: + undefiniert >> + "undefiniert" >> NaN. Da der numerische Kontext einen expliziten Wert erwartet.

Während der boolesche Kontext eine Referenz erwartet, findet er nichts zu konvertieren und ergibt 'false'.

Lass uns jetzt durchschneiden ...

Zitieren: Also noch einmal: Was ist die praktische Verwendung für separate Werte für undefiniert und null?

Ich werde versuchen, Ihnen nur zwei empirische Beispiele zu nennen, und hoffe, dass dies ausreicht

oElement.onclick >> null

// bedeutet - die Eigenschaft existiert; Der erwartete Wert ist vom Typ: Object , und dieses Element unterstützt das Ereignis "onclick"!

oElement.innerText >> ""

// bedeutet - die Eigenschaft existiert; Der erwartete Wert ist vom Typ: String . Dies bedeutet, dass oElement die Eigenschaft "innerText" unterstützt.

In beiden Fällen bedeutet dies, dass die Eigenschaft nicht vorhanden ist, wenn Sie "undefiniert" erhalten. wird nicht unterstützt oder hat eine falsche (ua Hersteller) Implementierung.

Bleib Frost und hab Spaß.


Zerstöre deine Beiträge nicht, aeneas. Löschen Sie sie (über die Schaltfläche Löschen direkt über diesem Kommentar), wenn Sie Ihren Beitrag entfernen möchten.
Michael Petrotta

Es gibt keine Schaltfläche zum Löschen - aber falls Sie es sehen - klicken Sie bitte darauf!

0

Nachdem ich eine erstaunliche Diskussion über undefined vs null gelesen hatte, führte mich eine kleine Suche bei Google zu Mozilla Documentations https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null Es wird oft erwähnt - null ist häufig Abgerufen an einem Ort, an dem ein Objekt erwartet werden kann, aber kein Objekt relevant ist.

Ist nicht ähnlich wie Null Objektmuster https://en.wikipedia.org/wiki/Null_object_pattern

Ich denke, dies ist sinnvoll, um den Datentyp Null zu haben.

Dokumentation auch als Typ von null // "Objekt" erwähnt (aus alten Gründen nicht "null")

Ich bin mir nicht sicher, was Legacy-Gründe sind

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.