在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
吗?
答案 0 :(得分:68)
问题不在于“为什么JS中存在空值” - 在大多数语言中存在某种类型的空值,通常认为它非常有用。
问题是,“为什么JS中存在 undefined 值”。使用它的主要地方:
'null'肯定也会起作用。 (3)应该立即抛出一个异常,而事实是它没有,而是返回这个奇怪的“未定义”,这将在以后失败,是调试难度的重要来源。
*:您也可以认为(2)应该抛出异常,但是您必须为默认/变量参数提供更好,更明确的机制。
然而,JavaScript最初没有异常,或者任何方式询问对象是否有某个名称下的成员 - 唯一的方法是(有时仍然是)访问该成员并查看您获得的内容。鉴于'null'已经有了一个目的,你可能想要设置一个成员,需要一个不同的带外值。所以我们有'未定义',这是有问题的,正如你指出的那样,这是另一个很棒的JavaScript'功能',我们永远无法摆脱它。
当我想取消设置不再使用但不想删除的属性值时,我实际上使用了undefined。我应该使用null吗?
是。保留'undefined'作为其他语言可能引发异常的信号的特殊值。
'null'通常更好,除了在一些IE DOM接口上设置'null'可能会给你一个错误。通常在这种情况下,设置为空字符串往往会起作用。
答案 1 :(得分:37)
最佳描述here,但总结如下:
undefined是缺少类型和值,null是缺少值。
此外,如果你正在进行简单的'=='比较,那么你是对的,它们也是一样的。但是尝试===,比较类型和值,你会发现差异。
答案 2 :(得分:16)
我认为没有任何理由同时拥有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
应该代表“不存在”。然而,实施并没有这样做。
答案 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)
和所有其他类型的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)
与Null对象模式不相似 https://en.wikipedia.org/wiki/Null_object_pattern
所以我觉得拥有Null数据类型是有意义的。
文档也提到了 typeof null //“object”(由于遗留原因,不是“null”)
不确定遗留原因是什么