2015-11-05 70 views
9

使用for...in我總是檢查hasOwnProperty(我的猜測是使用Object.keys一個很好的理由),如:ES6確實爲拿到的樣機值 - 如何檢查hasownproperty

for (let a in obj) { 
    if (obj.hasOwnProperty(a)) { 
     //logic 
    } 
} 

我需要做同樣的檢查當我使用for...of,如果是的話,我應該怎麼做?

按照MDN page on for...of

雖然for...in遍歷屬性名稱,for...of遍歷屬性值

但它並沒有說關於迭代是否包括繼承屬性或僅實例屬性什麼。給出的解釋和示例代碼只涉及實例屬性。

+2

爲什麼不直接看[文檔](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of)? – hindmost

+0

「for ... for循環與for ... in循環之間的區別。for ...在迭代屬性名稱時,用於...對屬性值進行迭代:」 – Ziki

+0

我做過了,它不是'如果它對自己的屬性進行迭代,則從它們中清除。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of – pQuestions123

回答

17

for...of遍歷一個可迭代對象的迭代器。在ES6規範中,通過Symbol.iterator屬性在對象上標識爲對象生成迭代器的函數;即someObj[Symbol.iterator]

對於每個可迭代類型,迭代器返回Symbol.iterator是不同的,但一般來說,它只會迭代對象所包含的值,這些值與該類型相關。例如:

添加屬性的對象的原型是不太可能影響到迭代器的行爲,所以在這方面不是必要的來測試該值是否來自自己的財產。

for..offor..in是根本不同的。for..in迭代對象的屬性,有時需要詢問有關這些屬性的問題,例如它們是否被繼承。 for..of將值從一個迭代器中抽出,它私下決定按什麼順序返回哪些值。詢問一個for..of迭代的結果是否來自繼承的屬性並不重要,因爲它可能根本不來自屬性。 (典型的例子,for..of迭代未暴露性質的Map返回值。)


我能想到的只有一個(極其奇怪的)情況,其中繼承屬性會影響一個Array的行爲迭代器,如果滿足以下所有都是真的:

  • 如果Array.prototype有一個整數名稱的屬性,並
  • 是整數命名屬性是設置爲流在實例正財產被迭代,
  • 實例的length比整數索引的名字

例如更大:

Array.prototype["7"] = "hello"; // why are you doing this?? :O 
var a = [1,2,3] 
a.length = 8;      // why are you doing this?? D: 
for(g of a) { console.log(g); } // great job, you got strange results 

在這種極其詭異的案子,你會遍歷在繼承的7屬性上。這實際上是我能想到的唯一案例;其他繼承的屬性將被忽略,因爲它們沒有整數名稱,或者因爲它們被具有相同整數名稱的實例屬性遮蔽,或者因爲它們大於或等於實例的length

0

您無法真正執行相同的檢查,因爲您沒有顯式訪問屬性密鑰。

var arr = [1, 2, 3]; 
for(let val of arr) { 
    // all you have is the value 
    // there is no way to check 
    console.log(val); 
} 

for-of語句可以與任何iterable object被使用,並且可迭代協議定義可以從對象變化的方式爲對象。

使用hasOwnProperty檢查的原因是爲了確保屬性位於對象上而不是對象的原型上。您可以輕鬆測試這是否與for-of相同。

var prototype = { a: 1 }; 
var instance = Object.create(prototype); 
instance.b = 2; 
instance.c = 3; 

for(var val of instance) { 
    console.log(val); 
} 

不同的環境都在此刻不同的for-of實現,它工作在我使用數組的瀏覽器,而不是物。最好的做法是在要部署到的環境中嘗試它。