ECMAScript Associative Array via Object w/ prototype null?
I see a lot of people doing this
Object.prototype.foo = 'HALLO';
var hash = {baz: 'quuz'};
for ( var v in hash ) {
// Do not print property `foo`
if ( hash.hasOwnProperty(v) ) {
console.log( v + " is a hash property" );
}
}
My question is rather than testing .hasOwnProperty
each time you wish to use an Object
as a hash why not just set the .__proto__
to null
on the object? †
hash.prototype = null;
hash.__proto__ = null;
for ( var v in hash ) {
// Do not print property `foo`
console.log( v + " is a hash property" );
}
It has been brought to my attention that __proto__
is nonstandard. That still doesn't answer the question though...
var foo = Object.create(null); Object.getPrototypeOf(foo);
This can't be an original question, but I can't find anything about ch开发者_如何学运维anging __proto__
to null
to eliminate the drawbacks of having to check for inheritance? What's wrong with this approach, seems to make code faster (don't have to check properties of Object
) and cleaner?
† And the .prototype
property if you plan on making future children of it.
There's nothing inherently wrong with creating [[Prototype]]'less objects to avoid hasOwnProperty
-based checks during "hash" enumeration.
In fact, some of the libraries I know (fuse.js being one of them, IIRC) do exactly that.
Now on to the practical problems:
__proto__ is non-standard. See my compat. table. Notice how IE doesn't support __proto__ up until and including IE9. Of course, IE9 supports
Object.create
and so it becomes possible to create [[Prototype]]'less object withObject.create(null)
but that still leaves IE6, IE7 and IE8. Oh and Opera <10.10, as you can see (which doesn't supportObject.create
). Fortunately, existence (and functionality) of __proto__ can be easily feature tested, which is why non-supporting browsers can be made to takehasOwnProperty
-based or some other route.Removing [[Prototype]] from the object "removes" all of the
Object.prototype.*
methods. Naturally. So, for example,myHash.toString()
(or evenmyHash + ''
) will now error out unless you give that hashtoString
method. Ditto forvalueOf
,hasOwnProperty
, and all the otherObject.prototype.*
methods. This isn't big deal, of course, as you can always define those methods (and probably should — to make them specialized for hash usage) but it's more work nevertheless.
As far not finding anything about this approach... I was talking about it at least 2 years ago :) — http://groups.google.com/group/comp.lang.javascript/msg/9451c45080b5e9f0 (likely earlier too, but can't find any other posts on comp.lang.javascript at the moment). There are more interesting findings about browsers' behavior with __proto__ === null in that thread. Check it out.
Not all JS implementations have __proto__
as it is non-standard feature.
精彩评论