为什么JavaScript中有一个`null`值?
在JavaScript中,有两个基本上说'我不存在'的值 – undefined
和null
。
程序员没有分配任何东西的属性将是undefined
,但为了使属性变为null
,必须明确地将null
分配给它。
我曾经认为需要null
因为undefined
是一个原始值, null
是一个对象。 它不是,即使typeof null
会产生'object'
:实际上,它们都是原始值 – 这意味着既没有undefined
也没有null
可以从构造函数返回,因为两者都将被转换为空对象(必须抛出一个错误宣布build设者失败)。
他们在布尔上下文中都评估为false
。 我能想到的唯一真正的区别是,在数值上下文中,一个评估为NaN
,另一个评估为0
。
那么,为什么会有这两个undefined
和null
如果这只是混淆了程序员谁试图找出一个属性是否已经设置或不正确检查null
?
编辑:我想知道的是,如果任何人有一个合理的例子,有必要使用null
不能用undefined
来表示。
edit2 + 3 :所以普遍的共识似乎是undefined
意思是“没有这样的属性”,而null
表示“属性确实存在,但没有任何价值”。
如果JavaScript实现能够实际执行此行为,我可以忍受这一点 – 但是undefined
是一个完全有效的原始值,因此可以轻松地将其分配给现有属性来破坏此合同。 因此,如果你想确定一个属性是否存在,你必须使用in
运算符或hasOwnProperty()
。 所以再次说明: undefined
和null
单独值的实际用法是什么?
我实际上使用undefined
当我想取消不再使用的属性的值,但我不想delete
。 我应该使用null
而不是?
这个问题不是真的“为什么JS中有一个空值” – 在大多数语言中都有一些空值,通常被认为是非常有用的。
问题是,“为什么JS中有一个未定义的值”。 主要使用地点:
- 当你声明'var x'时 但不分配给它,x保持未定义;
- 当你的函数获取的参数比它声明的less;
- 当你访问一个不存在的对象属性。
对于(1)和(2)*,“null”肯定会起作用。 (3)应该立即抛出一个exception,而事实并非如此,相反,这个错误的“未定义”将在以后失败,这是debugging困难的一个重要来源。
*:你也可以争辩说(2)应该抛出一个exception,但是你必须为default / variable参数提供一个更好,更明确的机制。
然而,JavaScript本来并没有例外,也没有任何方法来问一个对象,如果它有一个特定名称的成员 – 唯一的方法是(有时仍然是)访问该成员,看看你得到什么。 鉴于'null'已经有了一个目的,你可能想要为它设置一个成员,所以需要一个不同的带外值(out-of-band value)。 所以我们有'未定义',这是你指出的问题,这是另一个伟大的JavaScript'function',我们将永远不能摆脱。
我实际上使用未定义的,当我想取消不再使用的属性的值,但我不想删除。 我应该使用null而不是?
是。 当其他语言可能抛出一个exception时,保持“未定义”作为信号的特殊值。
'空'通常是更好的,除了一些IE DOM接口,其中设置为'null'可以给你一个错误。 通常在这种情况下设置为空string往往工作。
最好在这里描述,但总结:
undefined是缺less一个types和值,null是缺less一个值。
而且,如果你正在做简单的'=='比较,你是对的,它们也是一样的。 但尝试===,它会比较types和价值,你会注意到不同之处。
我不认为有什么理由可以同时使用null
和undefined
,因为许多人提出的唯一原因(“ undefined
意味着没有这样的variables/属性”)是无效的,至less在JavaScript中是这样的。 undefined
不能告诉你variables/属性是否存在。
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,则完全有可能让类返回具有空值的属性。 他们是被定义的,他们恰好在当时是空的。
我认为你把JavaScript定义为“不存在这样的属性”而null
为“属性没有价值”的结论是完全正确的。 在像JavaScript这样dynamic的语言中,这是一个非常重要的区别。 鸭子的使用意味着我们需要能够区分不存在的财产和没有价值的财产。 这是我们获取types信息的主要手段。 在静态types语言中,字段为空和字段不存在是明确的区别。 在JavaScript中,这是没有什么不同。 然而,它在运行时被检查,并可以被修改,直到那个时候。
我将不得不同意,这个实现很奇怪,因为很多时候这个区分是模糊的。 不过我认为在JavaScript中这个区别很重要。 能够分配undefined
是至关重要的。
我记得前一段时间读一篇关于用JavaScript编写的在线RPG的博文。 它使用的例子是把对象创build为现有实例的副本,而不是原型(类,函数,不pipe),然后进行修改。 这真的让我明白修改现有对象时undefined
function有多强大,但我不记得是谁写的。
在语义上它们意味着不同的东西。 nulltypes在其域中只有一个值,null可以为该特定值指定一个属性。 未定义代表已经分配的任何值的明显缺失。
作为一名Java程序员,我看到了undefined和null之间的巨大差异。 对JavaScript进行编码并不是很重要,因为JavaScript不是强types的,而且undefined和null之间的区别被运行时经常执行的自动转换所模糊。 顺便说一下,我经常利用这些转换。 他们使我的JS代码更加紧凑和可读。
要回答你的问题,未定义意味着一个值从来没有设置。 实际上,这通常指的是一个错误。 如果yourObject.property是未定义的,那意味着你没有设置属性出于某种原因,或者我正在寻找一些根本不存在的东西。 在使用多个编码器的项目上工作时,这是一个真正的问题。
null表示“没有值”被明确设置。 实际上,你是在告诉我有关财产的一些东西,或许这不是用在这种情况下,或者价值还没有确定。
在Java中,尝试访问未定义的字段将始终导致exception。 事实上,编译器可以在你的代码中提出警告。
试试这个例子:
<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>
我认为这里有两种不同types的非常实际的用途。
它归结为JavaScript的dynamic性质。
事情可能是未定义的,以便稍后添加它们。 这可以说是为什么JavaScript是如此强大和可扩展。
null是美丽的
所有其他types的Live Script也是如此。
引用:在JavaScript中,有两个基本上说'我不存在'的值 – undefined和null。
你为什么要说错误的东西?
“null”是“空对象” ,就像“0”是“空数字”一样 。 0,什么都不是 – 它存在作为一个数字types的东西。 null当然也是空的,但是“它是”,它是一个对象types的一个明确的东西。
如果不是,那么把这些东西称为“types”是很常见的。 实际上他们是“类别”。 但是现在已经结束了。
所以坚持说“null”是一种没有types的对象。 而“无效”说“我非常存在[!],但我没有我的内容”。
而undefined缺lessType和Kind,其中undefined碰巧也是它的Type定义。 一个未定义types的types成为其独特的types。 一种[没有什么是存在的,你怎么定义“没有”?]问题。
引用:未定义也不可以从构造函数返回null,因为两者都将转换为空对象
你已经设法再次说一个不正确的事情。 当然不是,“未定义”不是一个对象,它是我们人类理解的一个简单的令牌; 但与之相反的是 – 这是告诉你: 它的types是正确的,但是你所寻找的种类并不包含在其中,或者至less现在不是。 当我们把\对象分配给\时,请来拜访我们。
引用:我能想到的唯一真正的区别是,在数值上下文中,一个评估为NaN,另一个评估为0。
这就说明了它们的核心区别: undefined是一个简单的标记,由于它和远程亲属是相同的“遗传”材料:string,[+ undefined]操作会将其转换为NaN,类似的null当然会把自己变成一个正确的types0 \ Number,而不是undefined ,会变成一个string(!这不是空的!),这就是为什么它会产生NaN 。 其中:+ undefined >> +“undefined”>> NaN。 由于数字上下文需要显式值。
虽然布尔上下文期望引用 – 找不到任何转换,并产生“假”。
我们现在切入…
引用:所以再一次:对于undefined和null,单独值的实际用法是什么?
我会尽量给你们两个实证的例子,希望能够满足
oElement.onclick >> null
//手段 – 财产存在; 它的期望值是Type: Object ,而oElement支持“onclick”事件!
oElement.innerText >> ""
//手段 – 财产存在; 它的期望值是Type: String ,这意味着oElement支持“innerText”属性。
在这两种情况下 – 如果您收到“未定义”,则意味着该属性不存在; 不被支持或者有错误的(ua供应商)实现。
留下霜,玩得开心。
如果你将程序包装在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服务器非常明确和不同的目的。 在filter_func_pt对象中找不到的查找返回undefined意味着将属性添加到返回对象的原样,而空值表示该值应该被扣留,而不是添加,并在此存在任何真值case表示一个函数,用于在将值添加到ret对象之前对其进行转换。