2011-05-28 21 views
4

我看到很多人在做這個通過Object w/prototype null的ECMAScript關聯數組?

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"); 
    } 
} 

我的問題是,而不是爲什麼不設置.__proto__null對象上要使用的Object作爲哈希每次測試.hasOwnProperty? †

hash.prototype = null; 
hash.__proto__ = null; 

for (var v in hash) { 
    // Do not print property `foo` 
    console.log(v + " is a hash property"); 
} 

已經引起我注意的是__proto__是非標準的。儘管如此,這仍然不能回答這個問題。 Object.getPrototypeOf(foo);

這不可能是一個原始的問題,但我找不到任何改變__proto__null消除不必檢查繼承的缺點?這種方法有什麼問題,似乎使代碼更快(不必檢查Object的屬性)和更清潔?

†而.prototype財產,如果你打算將它的未來的孩子。

回答

4

沒有什麼內在錯誤與創建[[原型]]'較少的對象,以避免hasOwnProperty在「散列」枚舉期間的基於檢查。實際上,我認識的一些圖書館(fuse.js就是其中之一,IIRC)就是這麼做的。

現在到實際問題:

  1. __proto__是非標準。請參閱我的compat. table。請注意,在IE9之前IE如何不支持__proto__。當然,IE9支持Object.create,因此可以用Object.create(null)創建[[Prototype]]較少的對象,但仍然會留下IE6,IE7和IE8。哦,歌劇< 10.10,你可以看到(不支持Object.create)。幸運的是,__proto__的存在(和功能)可以輕鬆地進行功能測試,這就是爲什麼不支持的瀏覽器可以採用基於hasOwnProperty的路由或其他路由。

  2. 從對象中移除[[Prototype]]「移除」所有Object.prototype.*方法。自然。因此,例如,myHash.toString()(或甚至myHash + '')現在會出錯,除非您給出該散列toString方法。同上valueOf,hasOwnProperty,以及所有其他Object.prototype.*方法。這當然不是什麼大問題,因爲你總是可以定義這些方法(並且可能應該是--使它們專門用於哈希用法),但它仍然是更多的工作。

就沒有找到任何關於這種做法......我至少2年前說起吧:) - http://groups.google.com/group/comp.lang.javascript/msg/9451c45080b5e9f0(可能更早過,但找不到任何comp.lang其他職位。 JavaScript在此刻)。有關瀏覽器的行爲的更有趣的發現是__proto__ === null在該線程中。一探究竟。

+0

就像我說的,我很猶豫,說我先想到了它。只是我無法找到其他人討論它。 – 2011-06-04 16:51:25

0

並非所有的JS實現都有__proto__,因爲它是非標準功能。

+0

有沒有一種標準的方法來改變ECMA5中的對象的原型? – 2011-05-28 03:32:56

+1

沒有這樣的功能。 – 2011-05-28 03:41:13

+0

我不知道這回答這個問題,無論哪種方式,什麼關於空功能的技巧...基本的問題是,爲什麼沒有人擺脫繼承,而不是在每個使用點測試它?我不能成爲第一個想到這個想法的人。 – 2011-05-28 03:42:32