你可以在javascript中使属性可枚举但不可迭代吗?

Jim*_*nes 6 javascript ecmascript-6

我只是想知道是否有一种方法可以使对象属性像for in循环一样可枚举但不会出现在for of loop某种类似的东西中

Object.defineProperty({},'prop',{
    enumerable:true,
    iterable:false
}
Run Code Online (Sandbox Code Playgroud)

如果没有,有没有计划实现这样的功能?或者for of循环使用可枚举属性

小智 5

我在 Mozilla 开发网络 (MDN) 上做了一些挖掘。

原来,对象有一个obj.propertyIsEnumerable(prop)方法来检查属性是否可枚举。从 MDN 中给出的示例来看,通过原型链继承的属性是不可枚举的,因此该方法对这些属性返回 false。

不可枚举属性的一个例子是构造函数和length数组的属性。

对于问题的可迭代部分,我将引用 MDN:“ECMAScript 6 中的可迭代是一个接口(或者换句话说,一个协议),而不是像 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"]
Run Code Online (Sandbox Code Playgroud)

当然,您可以定义自己的迭代器实现。

回到这个问题,附加到对象或其原​​型的属性(直接,意味着不是通过继承)将在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
}
Run Code Online (Sandbox Code Playgroud)

let关键字是在这种情况下,以一个相当的var定义(尽管它有更多的含义,但他们超出这个职位的范围)。

正如你所看到的,数组已经有iterable接口的实现(来自数组原型),因此它在使用for...of循环时产生它的值,而foo没有显示属性(既没有值也没有属性名称)。

因此,如果您的对象没有实现iterable接口,则它不应该是可迭代的(原则上),因此它将在for...of循环中显示其属性。