这两个表达式的返回值之间有什么区别......
表达式1:typeof foo['bar'] !== 'undefined'
表达式2:'bar' in foo
...假设满足这些条件:
foo
是一个对象,foo
不包含任何明确设置值undefined
的属性。答案 0 :(得分:5)
第一个测试bar
中foo
的值。
第二次测试bar
中是否存在foo
属性。
var foo = {bar:undefined};
typeof foo['bar'] !== 'undefined'; // false
'bar' in foo; // true
修改强>
要从下面的评论中添加一些说明,OP的问题是访问domConfig
的{{1}}属性会引发错误。
这是与window.document
运算符无关的问题,而是与Firefox的特定问题有关。
问题has been documented here是一个错误(早在2003年)。
该报告中的一些值得注意的评论:
Zbigniew Braniecki [:gandalf] 2003-11-19 09:09:31太平洋标准时间
那为什么可以用for-in迭代它?
Boris Zbarsky(:bz)2003-11-19 09:24:05 PST
因为 被定义为nsIDOM3Document接口上的属性。它的 如果你试图访问其吸气剂,只会抛出一个。 ...
Zbigniew Braniecki [:gandalf] 2003-11-19 09:33:53太平洋标准时间
......那是什么类型的错误?
目标是从接口或删除未实现的方法/属性 实施它?!?
鲍里斯·扎巴斯基(:bz)2003-11-19 09:53:23太平洋标准时间
目标是最终实现这一目标。
答案 1 :(得分:2)
我对规范的解读表明它们应该是一样的。 “in”运算符语义是根据对内部(概念)[[HasProperty]]
方法的调用来定义的,该方法本身是根据[[GetProperty]]
定义的。当[[HasProperty]]
返回“undefined”时,“in”运算符会产生布尔值false
;否则它是true
。基于[[GetProperty]]
应该做什么的定义,这意味着属性访问的“未定义”结果具有相同的含义。
答案 2 :(得分:1)
var foo = {};
foo.bar = undefined;
console.log("bar" in foo); // true
console.log(typeof foo["bar"] !== "undefined"); // false
var Con = function() {};
Con.prototype.bar = undefined;
var foo = new Con;
console.log("bar" in foo); // true
console.log(typeof foo["bar"] !== "undefined"); // false
in
检查与使用for in
循环完全相同,如果key
在for in
循环中,则返回true。
[编辑]没有看到你的“不明确将其设置为undefined
”条件。
var foo = {}
Object.defineProperty(foo, "bar", {
"value": 42,
"enumerable": false
});
console.log("bar" in foo); // true (in chrome & FF4)
console.log(typeof foo["bar"] !== 'undefined'); // true
如果您将in
测试设置为不可枚举,我会非常期望var foo = {}
Object.defineProperty(foo, "bar", {
"value": 42,
"writable": false
});
console.log("bar" in foo); // true (in chrome & FF4)
console.log(typeof foo["bar"] !== 'undefined'); // true
测试失败。好像它们是一样的。
var foz = {}
Object.defineProperty(foz, "bar", {
"value": 42
});
var foo = Object.freeze(foz);
console.log("bar" in foo); // true (in chrome & FF4)
console.log(typeof foo["bar"] !== 'undefined'); // true
如果属性是“只读”,则两个测试仍然有效
{{1}}
冻结对象也不会破坏测试。
答案 3 :(得分:1)
鉴于你提出的条件,没有区别。两者都应该产生相同的布尔结果,并且应该在原型查找周围表现相同。
Object.prototype.hasOwnProperty.call(null, foo, 'bar')
是另一种常见的习惯用法,与这两种用法相同,但不包含仅在原型上可用的属性。
答案 4 :(得分:1)
鉴于这两个条件,表达式应该给出相同的结果,除非
foo
为bar
属性定义了一个EcmaScript 5 getter。由于第一个表达式实际上读取了属性值,因此将调用该getter。第二个表达式只检查属性的存在,因此不需要任何这样的getter。in
运算符;)这里有一些sample code来说明支持浏览器(Chrome,IE9,FF4)的区别:
var foo = {};
Object.defineProperty(foo, "bar", {
"get": function () {document.write("Getter invoked!<br/>"); return foo;}
});
document.write('"bar" in foo -->' +
("bar" in foo));
document.write('<br/>');
document.write('typeof foo["bar"] !== "undefined" -->' +
(typeof foo["bar"] !== "undefined"));
document.write('<br/>');
答案 5 :(得分:0)
第一个首先检查foo中是否存在'bar'键(如果未找到则返回undefined),然后检查该键的类型。 第二个只检查存在。