[英]Can you make properties enumerable but not iterable in javascript?
我只是想知道是否有一種方法可以使對象屬性可枚舉,就像在for in
循環中但不會出現在for of loop
類似
Object.defineProperty({},'prop',{
enumerable:true,
iterable:false
}
如果沒有,有沒有計划實現這樣的功能? 或者for of
循環使用了enumerable屬性
我在Mozilla開發網絡(MDN)上做了一些挖掘工作。
原來,對象有一個obj.propertyIsEnumerable(prop)
方法來檢查屬性是否可枚舉。 根據MDN中給出的示例,通過原型鏈繼承的屬性不可枚舉,因此該方法對這些屬性返回false。
不可枚舉屬性的一個示例是構造函數和數組的屬性length
。
對於問題的可迭代部分,我將引用MDN:“ECMAScript 6中的Iterable是一個接口(或者換句話說,一個協議),而不是像Array或Map這樣的對象類型”。
也就是說,對象需要實現此接口以使其屬性可迭代。 這是內置迭代的情況,例如String,Array,Map,Set,WeakSet和Generator對象。
以下代碼說明了這一點:
var aString = "hello"
typeof aString[Symbol.iterator] // "function"
aString[Symbol.iterator]() + "" // "[object String Iterator]"
[...aString] // ["h", "e", "l", "l", "o"]
當然,您可以定義自己的迭代器實現。
回到這個問題,附加到對象或其原型的屬性(直接,意思不是通過繼承)將在for...in
循環中顯示為可枚舉。 對於iterables,您需要一個實現,或者前面提到的實現,或者您自己的實現。 這是MDN的一個很好的例子。
let arr = [ 3, 5, 7 ];
arr.foo = "hello";
for (let i in arr) {
console.log(i); // logs "0", "1", "2", "foo" these are property names or indexes
}
for (let i of arr) {
console.log(i); // logs "3", "5", "7" these are actual values of an
// iterable implementation provided by the array prototype
}
let
關鍵字在此上下文中與var
定義等效(盡管它具有更多含義,但它們超出了本文的范圍)。
正如您所看到的,數組已經具有iterable
接口的實現(來自數組原型),因此在使用for...of
循環時會產生其值,而不顯示foo
屬性(既不是值也不是屬性名稱) 。
因此,如果您的對象沒有實現iterable
接口,那么它不應該是可迭代的(原則上),因此它將在for...of
循環中顯示其屬性。
for in
和for of
評估之間的區別在於,一個使用obj.[[enumerate]]
,另一個使用GetIterator(obj)
來確定循環項。 [[enumerate]]
確實 (除非obj
是代理)
返回一個Iterator對象,其
next
方法遍歷obj
的可枚舉屬性的所有String值鍵。
GetIterator
將(嘗試)調用@@iterate
方法 - 但是,普通對象不實現此接口。
因此for of
除非您明確說明,否則沒有屬性會出現在循環中:
function defineIterableProperty(obj, prop, desc) {
let old = obj[Symbol.iterate];
Object.defineProperty(obj, prop, desc);
obj[Symbol.iterate] = function* () {
if (old) yield* old.call(this);
yield prop;
};
return obj;
}
(未經測試,但我希望你能得到這個想法)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.