开发者

typeof foo['bar'] !== 'undefined' vs. 'bar' in foo

What's the difference between the return values of these two expressions...

Expression 1: typeof foo['bar'] !== 'undefined'

Expres开发者_如何学Pythonsion 2: 'bar' in foo

... assuming that these conditions are met:

  1. foo is an object,
  2. foo does not contain any properties that have the value undefined set explicitly.


The first tests the value of bar in foo.

The second tests for the existence of the bar property in foo.

var foo = {bar:undefined};

typeof foo['bar'] !== 'undefined'; // false

'bar' in foo;  // true

EDIT:

To add some clarification from the comments below, the issue OP is having is that accessing the domConfig property of window.document throws an Error.

This is an issue not related to the typeof operator, but rather to a specific issue with Firefox.

The issue has been documented here as a bug (back in 2003).

A few notable comments from that report:

Zbigniew Braniecki [:gandalf] 2003-11-19 09:09:31 PST

then why it can be iterated with for-in ?

Boris Zbarsky (:bz) 2003-11-19 09:24:05 PST

Because it is defined as a property on the nsIDOM3Document interface. It's just one that throws if you try to access its getter. ...

Zbigniew Braniecki [:gandalf] 2003-11-19 09:33:53 PST

... So what kind of bug is it?

The goal is to remove not implemented method/property from interface or to implement it?!?

Boris Zbarsky (:bz) 2003-11-19 09:53:23 PST

The goal is to eventually implement this.


My reading of the spec suggests that they should be the same. The "in" operator semantics are defined in terms of making a call to the internal (conceptual) [[HasProperty]] method, which itself is defined in terms of [[GetProperty]]. When [[HasProperty]] returns "undefined", then the "in" operator results in boolean false; otherwise it's true. Based on the definition of what [[GetProperty]] is supposed to do, that means that an "undefined" result of a property access would have the same meaning.


Given the conditions you outline, there is no difference. Both should produce the same boolean result and should behave the same around prototype lookup.

Object.prototype.hasOwnProperty.call(null, foo, 'bar')

is another common idiom that does the same as those two but does not incude properties available only on the prototype.


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

The in check is simply the same as using a for in loop and returning true if the key is in the for in loop.

[Edit] Didn't see your "don't explicity set it to undefined" condition.

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

I actaully expected the in test to fail if you set it as non-enumerable. Seems like they are the same.

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

Both test still work if the property is "readonly"

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

Freezing the object also doesn't break the tests.


Given those two conditions, the expressions should give you identical results, except if

  • foo has an EcmaScript 5 getter defined for the bar property. Since the first expression actually reads the property value, that getter will be invoked. The second expression merely checks for the existence of the property so there is no need to incoke any such getter.
  • you are targeting Internet Explorer 4.0 - the in operator wasn't added until JavaScript 1.4 ;)

Here's some sample code to illustrate the difference in supporting browsers (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/>');


the first one first checks existence of 'bar' key in foo (undefined is returned if it's not found), then checks the type of that key. the second on checks only existence.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜