为什么JavaScript中存在“null”值?

时间:2009-01-20 16:12:46

标签: javascript null language-features undefined

在JavaScript中,有两个值基本上表示“我不存在” - undefinednull

程序员未分配任何内容的属性为undefined,但为了使属性成为null,必须明确指定null

我曾经认为需要null因为undefined是原始值而null是一个对象。它不是,即使typeof null会产生'object':实际上,两者都是原始值 - 这意味着undefinednull都不能从构造函数返回,因为两者都将转换为空对象(必须抛出错误以声明构造函数中的失败)。

他们也在布尔上下文中评估false。我能想到的唯一真正的区别是,在数字上下文中,一个评估为NaN,另一个评估为0

那么为什么同时存在undefinednull,如果这只会让那些在尝试查找属性是否已设置时错误地检查null的程序员感到困惑?

我想知道的是,如果有人有合理的例子,那么必须使用null而不能用undefined表示。

所以普遍的共识似乎是undefined意味着'没有这样的财产',而null意味着'财产确实存在,但没有价值'。

如果JavaScript实现实际上会强制执行此行为,我可以忍受 - 但undefined是一个完全有效的原始值,因此可以轻松地将其分配给现有属性以破坏此合同。因此,如果您想确定属性是否存在,则无论如何都必须使用in运算符或hasOwnProperty()。再一次:undefinednull的单独值的实际用途是什么?

当我想取消设置不再使用的属性值但我不想undefined时,我实际使用delete。我应该使用null吗?

12 个答案:

答案 0 :(得分:68)

问题不在于“为什么JS中存在空值” - 在大多数语言中存在某种类型的空值,通常认为它非常有用。

问题是,“为什么JS中存在 undefined 值”。使用它的主要地方:

  1. 当您声明'var x;'时但不要分配给它,x保持未定义;
  2. 当你的函数获得的参数少于声明的参数时;
  3. 访问不存在的对象属性时。
  4. 对于(1)和(2)*,

    'null'肯定也会起作用。 (3)应该立即抛出一个异常,而事实是它没有,而是返回这个奇怪的“未定义”,这将在以后失败,是调试难度的重要来源。

    *:您也可以认为(2)应该抛出异常,但是您必须为默认/变量参数提供更好,更明确的机制。

    然而,JavaScript最初没有异常,或者任何方式询问对象是否有某个名称下的成员 - 唯一的方法是(有时仍然是)访问该成员并查看您获得的内容。鉴于'null'已经有了一个目的,你可能想要设置一个成员,需要一个不同的带外值。所以我们有'未定义',这是有问题的,正如你指出的那样,这是另一个很棒的JavaScript'功能',我们永远无法摆脱它。

      

    当我想取消设置不再使用但不想删除的属性值时,我实际上使用了undefined。我应该使用null吗?

    是。保留'undefined'作为其他语言可能引发异常的信号的特殊值。

    'null'通常更好,除了在一些IE DOM接口上设置'null'可能会给你一个错误。通常在这种情况下,设置为空字符串往往会起作用。

答案 1 :(得分:37)

最佳描述here,但总结如下:

undefined是缺少类型和值,null是缺少值。

此外,如果你正在进行简单的'=='比较,那么你是对的,它们也是一样的。但是尝试===,比较类型和值,你会发现差异。

答案 2 :(得分:16)

我认为没有任何理由同时拥有nullundefined,因为很多人建议的唯一原因(“undefined表示没有这样的变量/属性”)是无效的,至少在JavaScript中是这样。 undefined无法告诉您变量/属性是否存在。

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

如您所见,检查foo === undefined并不会告诉您foo是否存在,而设置obj.bar = undefined实际上并未删除bar

这可能是JavaScript作者的原始意图,undefined应该代表“不存在”。然而,实施并没有这样做。

答案 3 :(得分:6)

完全可能需要两者。例如,如果查询WMI,则完全可以使类具有null值的返回属性。它们被定义,它们恰好在当时保持为空。

答案 4 :(得分:6)

我认为你的结论是JavaScript将undefined定义为“没有这样的属性”而null为“属性没有价值”是完全正确的。在与JavaScript一样动态的语言中,这是一个非常重要的区别。使用duck typing意味着我们需要能够区分不存在的属性和没有值的属性。它是我们获取类型信息的主要手段。在静态类型语言中,字段为空和字段不存在之间存在明确区别。在JavaScript中,这没有什么不同。但是,它会在运行时进行检查,并且可以在此之前进行修改。

我将不得不同意实施很奇怪,因为很多时候区别模糊了。但是我认为在JavaScript中区别很重要。能够分配undefined至关重要。

我记得刚才读过一篇关于用JavaScript编写的在线RPG的博客文章。它使用了一些示例,其中对象被创建为现有实例的副本而不是原型(类,函数,等等),然后被更改。这真让我明白在修改现有对象时undefined有多强大,但我不记得是谁写的。

答案 5 :(得分:3)

从语义上讲,它们意味着不同的东西。 null类型在其域中只有一个值,null,并且可以为该属性分配该特定值。未定义表示已分配任何值的明显缺失。

答案 6 :(得分:3)

作为Java程序员,我发现undefined和null之间存在巨大差异。编码JavaScript,而不是因为JavaScript没有强类型,并且undefined和null之间的差异由运行时经常执行的自动转换模糊。顺便说一句,我经常利用这些转换;它们使我的JS代码更加紧凑和可读。

要回答您的问题,undefined表示从未设置过值。实际上,这通常指向一个错误。如果yourObject.property未定义,这意味着您由于某种原因没有设置属性,或者我正在寻找根本不存在的东西。在处理具有多个编码器的项目时,这是一个真正的问题。

null表示显式设置了“无值”。实际上,你告诉我一些关于该属性的信息,也许是在这种情况下没有使用它,或者还没有确定一个值。

在Java中,尝试访问未定义的字段将始终导致异常。实际上,编译器可以在您的代码中向您发出警告。

答案 7 :(得分:0)

试试这个例子:

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

我认为这里有两种不同类型的实际用途。

答案 8 :(得分:0)

它归结为javascripts动态性。

事情可能未定义,以便稍后可以添加。这可以说是javascript如此强大和可扩展的原因。

答案 9 :(得分:0)

如果你将程序包装在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)

如果您正在处理一组需要表示“无”的数据来表示某些操作与使用“nothing”表示默认操作不同,这非常有用。

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

在上面的代码中 null 关键字和 undefined 服务器非常明确和不同的目的。返回 undefined 的filter_func_pt对象中找不到的查找意味着按原样将属性添加到返回对象,而 null 值表示应该保留该值,而不是添加,并且在这种情况下存在任何真值表示在将值添加到 ret 对象之前用于转换值的函数。

答案 10 :(得分:0)

null很漂亮

和所有其他类型的Live Script一样。

  

cite:在JavaScript中,有两个值基本上都是'我不知道   存在' - undefined和null。

为什么要说不正确的事情?!

“null”“空对象”就像“0”是“空数字”。 0,没什么 - 它作为一个数字类型存在。 null 当然也是空的,但“它是”,它是一个明确定义的对象类型

当它们不是“类型”时,通常会说这些东西。实际上它们是“类别”。但现在已经结束了。

因此,坚持认为“null”是一种没有种类的对象。 并且“null”说“我非常存在[!],但我没有我的内容”。

undefined 缺少Type和Kind,其中 undefined 恰好也是它的Type定义。未定义类型的类型成为其独特的类型。 有一种[没有“存在”,你如何定义“没有”?]问题。

  

引用:从构造函数返回undefined和null,   因为两者都将转换为空对象

你已经设法再次说出一个不正确的事情。当然不是,“未定义”不是一个对象,它是我们人类理解的普通令牌;但与 null 相反的是 - 它告诉你:它的类型是正确的,但你正在寻找的种类不包含在其中,或者至少在此时不包含。稍后当我们将\中的一些对象分配给它时,请访问我们。

  

引用:我能想到的唯一真正的区别是,一个人评估为   NaN,另一个在数字上下文中为0。

这就是他们核心区别的重点,如上所述: undefined 是一个简单的标记,因为它由与其远亲相同的“遗传”材料组成:字符串,[ + undefined]操作将鸭子转换为NaN,类似于null当然会将自身变形为正确的种类0 \ Number,而不是 undefined 将变形成一个字符串(!这是不是空的!)而这正是它产生 NaN 的原因。其中:+ undefined&gt;&gt; +“undefined”&gt;&gt; NaN的。由于数字上下文需要显式值。

虽然布尔上下文需要引用 - 找不到要转换的内容并产生'false'。

让我们现在切断......

  

引用:再一次:单独值的实际用途是什么   undefined和null?

我将尽力给你两个经验实例并希望足够

oElement.onclick >> null

//表示 - 属性存在;它的预期值是Type: Object ,而oElement支持“onclick”事件!

oElement.innerText >> ""

//表示 - 属性存在;它的预期值是Type: String ,这意味着oElement支持“innerText”属性。

在两种情况下 - 如果您收到“未定义”,则表示该属性不存在;不受支持或有错误的(供应商)实施。

保持霜冻,玩得开心。

答案 11 :(得分:0)

在阅读关于undefined vs null的惊人讨论之后,google上的小搜索将我带到了Mozilla Documentations https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null 它被提到 - 通常在可以预期对象但没有对象相关的位置检索null。

与Null对象模式不相似 https://en.wikipedia.org/wiki/Null_object_pattern

所以我觉得拥有Null数据类型是有意义的。

文档也提到了 typeof null //“object”(由于遗留原因,不是“null”)

不确定遗留原因是什么