124

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

程序员没有分配任何东西的属性 will be undefined,但为了让属性成为nullnull必须显式分配给它。

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

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

那么为什么两者都存在undefinednull如果这只会让程序员null在试图找出是否设置了属性时错误地检查呢?

我想知道的是,是否有人有一个合理的例子,必须使用null它不能用undefined代替来表达。

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

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

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

4

12 回答 12

87

问题并不是真正的“为什么 JS 中有一个空值”——在大多数语言中都有某种空值,它通常被认为非常有用。

问题是,“为什么 JS 中有未定义的值”。主要使用场所:

  1. 当您声明var x;但未分配给它时,x保持未定义;
  2. 当你的函数得到的参数比它声明的少时;
  3. 当您访问不存在的对象属性时。

null对于 (1) 和 (2)* 肯定也同样有效。(3) 真的应该立即抛出异常,而事实上它没有返回这个undefined稍后会失败的怪异,这是调试困难的一大来源。

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

然而,JavaScript 最初并没有例外,也没有任何方式来询问对象是否有某个名称下的成员 - 唯一的方法是(有时仍然是)访问该成员并查看你得到了什么。鉴于它null已经有了一个目的,并且您可能希望为其设置一个成员,因此需要一个不同的带外值。所以我们有了undefined,正如你所指出的那样,它是有问题的,它是我们永远无法摆脱的另一个伟大的 JavaScript“功能”。

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

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

null通常会更好,除了在某些 IE DOM 接口上设置某些内容null可能会给您带来错误。通常在这种情况下,设置为空字符串往往会起作用。

于 2009-01-21T00:00:05.297 回答
38

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

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

此外,如果您正在进行简单的“==”比较,那么您是对的,它们的结果是一样的。但是试试 ===,它比较类型和值,你会注意到不同之处。

于 2009-01-20T16:18:16.103 回答
18

我认为没有任何理由同时拥有nulland undefined,因为许多人建议的唯一原因(“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

undefined应该代表“不存在”的可能是 JavaScript 作者的初衷。然而,实施的结果并非如此。

于 2012-10-18T19:38:23.367 回答
6

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

于 2009-01-20T16:17:52.763 回答
6

我认为您将 JavaScript 定义undefined为“没有这样的属性”和null“该属性没有价值”的结论是完全正确的。在像 JavaScript 这样动态的语言中,这是一个非常重要的区别。使用鸭子类型意味着我们需要能够区分不存在的属性和不具有值的属性。它是我们获取类型信息的主要方式。在静态类型语言中,字段为空和字段不存在之间有明确的区别。在 JavaScript 中,这没有什么不同。然而,它在运行时被检查,并且可以在那个时候被修改。

我将不得不同意实施很奇怪,因为很多时候区分是模糊的。但是我认为在 JavaScript 中区别很重要。并且能够分配undefined是必不可少的。

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

于 2009-01-20T17:45:24.397 回答
3

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

于 2009-01-20T16:21:23.040 回答
3

作为一名 Java 程序员,我看到了 undefined 和 null 之间的巨大差异。编写 JavaScript 代码不多,因为 JavaScript 不是强类型的,并且 undefined 和 null 之间的区别被运行时经常执行的自动转换模糊了。顺便说一句,我经常利用这些转换;它们使我的 JS 代码更加紧凑和可读。

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

null 表示明确设置了“无值”。实际上,您是在告诉我有关该属性的一些信息,可能是在此上下文中未使用它,或者尚未确定值。

在 Java 中,尝试访问未定义的字段总是会导致异常。事实上,编译器可以在你的代码中警告你这一点。

于 2012-04-11T14:25:06.083 回答
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>

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

于 2009-01-20T17:04:05.260 回答
0

它归结为javascripts动态性质。

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

于 2009-01-20T17:30:40.310 回答
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)

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

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 server 很清楚,用途不同。在返回undefined的 filter_func_pt 对象中找不到的查找意味着将属性按原样添加到返回对象中,而null值表示应该保留该值,而不是添加该值,并且此值中存在任何真值case 表示一个函数,用于在将值添加到ret对象之前对其进行转换。

于 2011-02-24T21:25:06.867 回答
0

空是美丽的

与所有其他类型的实时脚本一样。

引用:在 JavaScript 中,有两个值基本上表示“我不存在” - undefined 和 null。

为什么要说不正确的话?!

"null""empty Object",就像 "0" 是"empty Number"。0,什么都不是——但它作为数字类型存在。 null当然也是空的,但“它是”,它是一个明确定义的对象类型

通常将这些东西称为“类型”,而实际上它们不是。事实上,它们是“类别”。但现在已经结束了。

所以会坚持说“null”是一种没有种类的对象类型。“null”表示“我非常存在[!],但我没有我的内容”。

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

cite: undefined 或 null 可以从构造函数返回,因为两者都将转换为空对象

你又一次说了不正确的话。当然不是,“未定义”不是 Object,它是我们人类理解的普通 Token;但与null相反的是 - 它告诉你:它的 Type 是正确的,但你正在寻找的 Kind 不包含在其中,或者至少 - 目前不包含。稍后当我们将一些对象放入\分配给它时来拜访我们。

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

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

虽然布尔上下文需要引用 - 找不到任何要转换的内容并产生“假”。

现在让我们切入...

引用:所以再一次:未定义和空值的单独值的实际用途是什么?

我将尝试只给你两个经验性的例子,希望就足够了

oElement.onclick >> null

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

oElement.innerText >> ""

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

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

保持霜冻,玩得开心。

于 2012-02-09T01:16:11.200 回答
0

在阅读了关于 undefined vs null 的惊人讨论后,在谷歌上的小搜索把我带到了 Mozilla 文档 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”,因为遗留原因)

不确定遗留原因是什么

于 2018-03-17T10:36:23.530 回答