2012-10-04 30 views
51

可能重複:
How do I check to see if an object has a property in Javascript?的for..in和hasOwnProperty

我發現Twitter的JS文件,下面的代碼片段。我想知道爲什麼他們需要調用hasOwnProperty函數來查看'dict'是否具有'key'屬性? for循環爲'dict'中的每個'key'運行,這意味着'dict'有'key',我錯過了一個點嗎?

function forEach(dict, f) { 
    for (key in dict) { 
     if (dict.hasOwnProperty(key)) 
      f(key, dict[key]); 
    } 
} 
+3

這裏有很好的解釋:http://stackoverflow.com/a/136411/27512 – kevingessner

+0

好像'key'是全球性的這個代碼來自哪裏,你可以發佈一個鏈接嗎? – elclanrs

+0

@elclanrs我錯了。此代碼來自Chrome的utils.js – scusyxx

回答

54

因爲如果你不這樣做,它會通過對原型鏈,包括那些你不知道(這是可能被人用原生對象原型搞亂加)每個屬性循環。

這樣,您只能保證該對象實例本身的密鑰。

+0

非常感謝。現在更有意義.. – scusyxx

5

JavaScript的每個對象是一本字典,這意味着「的toString」和所有其他的方法是每一個對象

var myObj = {}; 
console.log(myObj["toString"]); 

的關鍵,但這個功能是從Object類繼承,如果這樣hasOwnProperty告訴你密鑰由字典所有,或者如果它被繼承。

"toString" in myObj; // true 
myObj.hasOwnProperty("toString") // false 
1

@blockhead就在這裏。例如,Prototype.js框架用於使用額外的輔助方法擴展本地數組(我不知道當前版本框架的情況)。 因此,直接使用「for(key in dict)」將返回div的所有元素以及對輔助方法的引用。這是一種意想不到的:)

26

hasOwnProperty方法讓你知道一個屬性是直接在一個對象的實例上還是從它的原型鏈繼承而來。

考慮以下

function ObjWithProto() { 
    this.foo = 'foo_val'; 
} 

ObjWithProto.prototype = {bar: 'bar_val'}; 

var dict = new ObjWithProto(); 
dict.foobar = 'foobar_val'; 

即你有一個對象dict與性能foofoobar也從它的原型鏈繼承屬性bar

現在運行它通過(修改版),你的代碼

function forEach(dict) { 
    var key; 
    for (key in dict) { 
     if (dict.hasOwnProperty(key)) console.log('has', key, dict[key]); 
     else console.log('not', key, dict[key]); 
    } 
} 
forEach(dict); 

你會看到

has foo foo_val 
has foobar foobar_val 
not bar bar_val 

這讓你單獨的屬性對象具有本身和那些它繼承(其中通常是與循環無關的方法)

此外,如果您現在執行dict.bar = 'new_bar_val';,最後的結果將更改爲has bar new_bar_val,讓您甚至可以區分與繼承的同名屬性。