在JavaScript中,有两个基本上说'我不存在'的值 - undefined
和null
.
程序员未分配任何内容undefined
的属性将是,但为了使属性成为必需null
,null
必须明确分配给它.
我曾经认为需要null
因为undefined
原始价值和null
对象.它不是,即使typeof null
会产生'object'
:实际上,两者都是原始值 - 这意味着既不能undefined
也不null
能从构造函数返回,因为它们都将被转换为空对象(必须抛出错误来宣告构造函数中的失败).
它们也都false
在布尔上下文中进行求值.唯一真正的区别我能想到的是,一个计算结果为NaN
,其他0
的数字环境.
那么为什么会出现这两种情况undefined
,null
如果这只会让那些null
在试图找出属性是否已经设置时错误检查的程序员感到困惑?
我想知道的是,如果有人有一个合理的例子,那就是必须使用null
而不是用来表示undefined
.
因此,普遍的共识似乎undefined
是"没有这样的财产",而null
意味着"财产确实存在,但没有价值".
我可以忍受,如果JavaScript实现实际上会强制执行此行为 - 但它undefined
是一个完全有效的原始值,因此可以很容易地将其分配给现有属性以破坏此合同.因此,如果要确定属性是否存在,则必须使用in
运算符或hasOwnProperty()
任何方式.再一次:对于undefined
和的单独值的实际用途是null
什么?
我实际上undefined
在我想要取消设置不再使用但我不想要的属性值时使用delete
.我应该用null
吗?
问题不是"为什么JS中存在空值" - 在大多数语言中存在某种类型的空值,并且通常认为它非常有用.
问题是,"为什么JS中存在未定义的值".使用它的主要地方:
当你声明'var x;'时 但不要分配给它,x保持未定义;
当你的函数获得的参数少于声明的参数时;
当您访问不存在的对象属性时.
对于(1)和(2)*,'null'肯定也会起作用.(3)应该立即抛出一个异常,并且事实上它不会,而是返回这个奇怪的"未定义",这将在以后失败,是调试难度的重要来源.
*:你也可以争辩说(2)应该抛出异常,但是你必须为默认/变量参数提供更好,更明确的机制.
然而,JavaScript最初没有异常,或者任何方式询问对象是否有某个名称下的成员 - 唯一的方法是(有时仍然是)访问该成员并查看您获得的内容.鉴于'null'已经有了一个目的,你可能想要设置一个成员,需要一个不同的带外值.所以我们有'未定义',这是有问题的,正如你指出的那样,这是另一个伟大的JavaScript'功能',我们永远无法摆脱.
当我想取消设置不再使用的属性值但我不想删除时,我实际上使用了未定义.我应该使用null吗?
是.保持'undefined'作为信号的特殊值,当其他语言可能引发异常时.
'null'通常更好,除了在一些IE DOM接口上设置'null'可能会给你一个错误.通常在这种情况下,设置为空字符串往往起作用.
最好的形容这里,但在汇总:
undefined是缺少类型和值,null是缺少值.
此外,如果你正在做简单的'=='比较,那么你是对的,它们也是一样的.但是尝试===,比较类型和值,你会发现差异.
我不认为有任何理由,同时拥有null
和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
.
它可能是JavaScript作者的原始意图,undefined
应该代表"不存在".但是,实施并没有这样做.
完全可能需要两者.例如,如果查询WMI,则完全可以使类具有null值的返回属性.它们被定义,它们恰好在当时保持为null.
我认为你的结论是JavaScript定义undefined
为"没有这样的属性"和null
"属性没有价值"是完全正确的.在与JavaScript一样动态的语言中,这是一个非常重要的区别.使用duck typing意味着我们需要能够区分不存在的属性和没有值的属性.它是我们获取类型信息的主要手段.在静态类型语言中,字段为空和字段不存在之间存在明确区别.在JavaScript中,这没有什么不同.但是,它会在运行时进行检查,并且可以在此之前进行修改.
我将不得不同意实施很奇怪,因为很多时候区别模糊.但是我认为在JavaScript中区别很重要.能够分配undefined
是必不可少的.
我记得刚才读过一篇关于用JavaScript编写的在线RPG的博客文章.它使用了一些示例,其中对象被创建为现有实例的副本而不是原型(类,函数,等等),然后被更改.这真让我明白undefined
在修改现有对象时有多强大,但我不记得是谁写的.