168

当它说“for..in 迭代对象的可枚举属性”时,我被定向到 MDN 的for..in 页面。

然后我转到属性的可枚举性和所有权页面,上面写着“可枚举的属性是那些可以通过 for..in 循环迭代的属性”。

字典将 enumerable 定义为可数的,但我无法真正想象这意味着什么。我可以举一个可枚举的例子吗?

4

8 回答 8

174

可枚举属性是可以在for..in循环(或类似的属性迭代,如Object.keys())中包含和访问的属性。

如果一个属性未被标识为可枚举,则循环将忽略它在对象内。

var obj = { key: 'val' };

console.log('toString' in obj); // true
console.log(typeof obj.toString); // "function"

for (var key in obj)
    console.log(key); // "key"

属性由其自身的[[Enumerable]]属性标识为可枚举或不可枚举。您可以将其视为属性描述符的一部分:

var descriptor = Object.getOwnPropertyDescriptor({ bar: 1 }, 'bar');

console.log(descriptor.enumerable); // true
console.log(descriptor.value);      // 1

console.log(descriptor);
// { value: 1, writable: true, enumerable: true, configurable: true }

然后for..in循环遍历对象的属性名称。

var foo = { bar: 1, baz: 2};

for (var prop in foo)
    console.log(prop); // outputs 'bar' and 'baz'

但是,只评估它的声明——console.log(prop);在这种情况下——对于那些属性为 的[[Enumerable]]属性true

这个条件是存在的,因为对象有更多的属性,尤其是继承

console.log(Object.getOwnPropertyNames(Object.prototype));
// ["constructor", "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", /* etc. */]

这些属性中的每一个仍然存在于对象上

console.log('constructor' in foo); // true
console.log('toString' in foo);    // true
// etc.

但是,它们被for..in循环跳过,因为它们不可枚举。

var descriptor = Object.getOwnPropertyDescriptor(Object.prototype, 'constructor');

console.log(descriptor.enumerable); // false
于 2013-07-27T02:47:12.407 回答
52

如果您通过或其他方式创建对象myObj = {foo: 'bar'},则所有属性都是可枚举的。所以更容易问的问题是,什么是不可枚举的?某些对象有一些不可枚举的属性,例如如果你调用Object.getOwnPropertyNames([])(它返回一个包含所有属性的数组,无论是否可枚举,在 [] 上),它会返回['length']包含数组的不可枚举属性“length” .

您可以通过调用创建自己的不可枚举属性Object.defineProperty

var person = { age: 18 };
Object.defineProperty(person, 'name', { value: 'Joshua', enumerable: false });

person.name; // 'Joshua'
for (prop in person) {
  console.log(prop);
}; // 'age'

此示例大量借鉴了 JavaScript 中的不可枚举属性,但显示了一个正在枚举的对象。属性可以是可写的、可配置的或可枚举的,也可以不是。John Resig 在ECMAScript 5 Objects and Properties的范围内讨论了这个问题。

而且,还有一个 Stack Overflow 问题,关于为什么你想让属性成为不可枚举的

于 2013-07-27T02:59:19.133 回答
40

它比应该可视化的东西无聊得多。

从字面上看,所有属性都有一个属性,称为“可枚举”。当它设置为 false 时,该for..in方法将跳过该属性,假装它不存在。

对象上有很多属性将“enumerable”设置为 false,例如“valueOf”和“hasOwnProperty”,因为假定您不希望 JavaScript 引擎遍历这些属性。

您可以使用以下方法创建自己的不可枚举属性Object.defineProperty

  var car = {
    make: 'Honda',
    model: 'Civic',
    year: '2008',
    condition: 'bad',
    mileage: 36000
  };

  Object.defineProperty(car, 'mySecretAboutTheCar', {
    value: 'cat pee in back seat',
    enumerable: false
  });

现在,甚至关于汽车的秘密都被隐藏了。当然他们仍然可以直接访问该属性并得到答案:

console.log(car.mySecretAboutTheCar); // prints 'cat pee in back seat'

但是,他们必须首先知道该属性存在,因为如果他们试图通过它访问它,for..in否则Object.keys它将完全保密:

console.log(Object.keys(car)); //prints ['make', 'model', 'year', 'condition', 'mileage']

他们应该称之为“forInAble”。

于 2015-11-19T07:21:47.113 回答
10

我会写一行ENUMERABLE的定义

Enumerable:指定属性是否可以在 for/in 循环中返回。

var obj = {};
Object.defineProperties(obj, {
    set1: {enumerable: true},
    set2: {enumerable: false},
});
Object.keys(obj); // ["set1"]
Object.getOwnPropertyNames(obj); // ["set1", "set2"]
于 2016-08-02T13:26:43.773 回答
9

如果您难以想象“可枚举是什么意思?” 为什么不问问自己,不可数是什么意思

我想它有点像这样,一个不可枚举的属性存在但部分隐藏;这意味着不可数是奇怪的。现在您可以将 enumerable 想象成剩下的东西——自从我们发现Objects以来,我们习惯于遇到的更自然的属性。考虑

var o = {};
o['foo'] =  0;                               // enumerable, normal
Object.defineProperty(o, 'bar', {value: 1}); // nonenumerable, weird

现在在 a 中for..in,想象它像伪代码

for property in o:
    if not property enumerable continue // skip non-enumerable, "bar"
    else do /* whatever */              // act upon enumerable, "foo"

你在JavaScript中输入的循环体在哪里/* whatever */

于 2013-07-27T03:01:27.287 回答
3

对象继承的内置方法不可枚举,但您的代码添加到对象的属性是可枚举的,除非明确说明

于 2019-11-26T15:11:04.297 回答
1

想想枚举数据类型,只是对应不同数字的对象结构。将某事物声明为可枚举就是声明它对应于一个特定的数字,从而允许它在表示对象的可数组件的字典中被赋予一个位置。简单地说,使一个对象可枚举就像告诉编译器,“嘿,这个属性很重要,我想在检查这个对象的数据时看到这个。”

于 2019-11-01T12:14:03.010 回答
0

方法不可枚举;或者更确切地说,内置方法不是......在搜索可枚举 对java脚本意味着什么之后;它只是指一个属性属性.. 在 ecma3 中创建的所有对象都是可枚举的,并且 ecma5 你现在可以定义它.. 就是这样.. :D 哈哈花了我一点时间才找到答案;但我相信它在大卫弗拉纳根的书中谈到......所以我猜它的意思是“隐藏”,或者不是“隐藏”,因为方法没有显示在 for in 循环中,因此是“隐藏的”

于 2015-12-04T22:11:14.640 回答