我想知道是否有一种方法可以使对象属性像在for in
循环中一样可枚举,但不会出现在for of loop
中。
Object.defineProperty({},'prop',{
enumerable:true,
iterable:false
}
如果没有,是否有计划实现这样的功能?或者for of
循环是否使用可枚举属性?
我想知道是否有一种方法可以使对象属性像在for in
循环中一样可枚举,但不会出现在for of loop
中。
Object.defineProperty({},'prop',{
enumerable:true,
iterable:false
}
如果没有,是否有计划实现这样的功能?或者for of
循环是否使用可枚举属性?
我在Mozilla开发者网络(MDN)上进行了一些调查。
事实证明,对象有一个obj.propertyIsEnumerable(prop)
方法来检查属性是否可枚举。从MDN中给出的示例来看,通过原型链继承的属性是不可枚举的,因此对于这些属性,该方法返回false。
非可枚举属性的一个例子是构造函数和数组的length
属性。
至于问题中提到的可迭代部分,我将引用MDN的说法:“ECMAScript 6中的可迭代是一个接口(或者换句话说,协议),而不是像数组或映射这样的对象类型”。
也就是说,对象需要实现此接口才能使其属性可迭代。内置可迭代对象(如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
循环中显示为可枚举。对于可迭代对象,您需要一个实现,可以使用之前提到的实现或者自己编写。这里有一个来自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
是代理对象)返回一个迭代器对象,其
next
方法遍历obj
可枚举属性的所有字符串键。
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;
}
< p > (未经测试,但我希望您能理解我的意思)