我认为有四种不同的方法可以确定给定对象(例如foo
)是否定义了给定属性(例如bar
):
if (foo.hasOwnProperty(bar)) {
if ('bar' in foo) {
if (typeof foo.bar !== 'undefined') {
if (foo.bar === undefined) {
要确定对象foo
中是否存在名为“bar
”的属性,这三个语句都是等效的吗?是否存在我不知道的微妙语义使得这些语句中的任何一个与其他语句不同?
我认为有四种不同的方法可以确定给定对象(例如foo
)是否定义了给定属性(例如bar
):
if (foo.hasOwnProperty(bar)) {
if ('bar' in foo) {
if (typeof foo.bar !== 'undefined') {
if (foo.bar === undefined) {
要确定对象foo
中是否存在名为“bar
”的属性,这三个语句都是等效的吗?是否存在我不知道的微妙语义使得这些语句中的任何一个与其他语句不同?
foo = {bar: undefined};
Object.prototype.baz = undefined;
Object.prototype.bing = "hello";
那么:
(typeof foo.bar != "undefined") === false
('bar' in foo) === true
(foo.hasOwnProperty('bar')) === true
(typeof foo.baz != "undefined") === false
('baz' in foo) === true
(foo.hasOwnProperty('baz')) === false
(typeof foo.bing != "undefined") === true
('bing' in foo) === true
(foo.hasOwnProperty('bing')) === false
逻辑上:
foo.hasOwnProperty('bar')
意味着 'bar' in foo
typeof foo.bar != "undefined"
意味着 'bar' in foo
它们都是不同的:
foo.hasOwnProperty('bar')
可以告诉你 foo
是否有这个属性,但不查找原型链。
'bar' in foo
检查原型链,并返回true,当它在链中的任何对象中找到属性 bar
时。
typeof foo.bar != 'undefined'
返回true,如果 foo
或其原型链中的任何对象具有属性 bar
并且其值不是 undefined
。
下面是一个演示这些差异的示例:
var foo1 = { 'bar1': 10, 'bar2': undefined };
function ctor() {}
ctor.prototype = foo1;
var foo2 = new ctor();
foo2.bar3 = 20;
console.log(foo2.hasOwnProperty('bar1')); // false
console.log(foo2.hasOwnProperty('bar2')); // false
console.log(foo2.hasOwnProperty('bar3')); // true
console.log(foo2.hasOwnProperty('bar4')); // false
console.log('bar1' in foo2); // true
console.log('bar2' in foo2); // true
console.log('bar3' in foo2); // true
console.log('bar4' in foo2); // false
console.log(typeof foo2.bar1 != 'undefined'); // true
console.log(typeof foo2.bar2 != 'undefined'); // false
console.log(typeof foo2.bar3 != 'undefined'); // true
console.log(typeof foo2.bar4 != 'undefined'); // false
一个不同之处在于,方法1仅检查属性“bar”的foo对象,而后两种方法还将检查原型以获取继承属性。
'bar' in foo
在原型链上的任何地方都可以查找。测试 foo.bar
!== undefined
,如果 bar
在 foo
的原型链上的任何位置,也会返回 true,但请记住,如果 bar 已经在 foo 上定义,并且设置为 undefined,则此方法将返回 false。
hasOwnProperty 更加挑剔 - 它只有在 bar
作为 foo
的直接属性被定义时才会返回 true。
根据 MDN
从 Object 继承的每个对象都继承了 hasOwnProperty 方法。该方法可用于确定对象是否具有指定属性作为该对象的直接属性;与 in 运算符不同,此方法不检查对象的原型链。
各种方法/关键字之间确实存在一些微妙的差异。
foo.hasOwnProperty('bar')
仅在foo对象本身上定义了属性'bar'时返回true。但是,其他属性(例如'toString')将返回false,因为它们定义在原型链上。
关键字操作符in
如果指定的属性在指定的对象中,则返回true。 'bar' in foo
和'toString' in foo
都会返回true。
由于您正在检查属性的状态,因此当foo上未定义bar并且bar已定义但值设置为undefined
时,结果将为true。
undefined
,null
,false
,0
,""
,NaN
等),你可以这样做:if (foo.bar) {
// code here
}
if ('bar' in foo) {
// code here
}
如果您不关心假值,也可以在函数参数上使用类似的方法:
function foo(bar) {
if (bar) {
// bar was passed and has some non-falsey value
}
}
undefined
变量,否则也可以将 3 写成if (foo.bar !== undefined) {
。 - Domenic