枚举是什么意思?


151

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

然后,我转到属性可枚举和所有权页面,其中显示“可枚举的属性是可以通过for..in循环进行迭代的那些属性”。

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


你明白for-in吗?

从答案中,我得到了for..in,它允许将对象的所有可枚举属性与for语句一起使用
Patrick

6
最简单的含义是:一个属性是否由for in循环产生(对于那些不想知道细节或只是不在乎的人;)
Tomasz Racia 2015年

Answers:


158

可枚举的属性是可以在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

因此构造函数属性是不可枚举的,因为它不会显示在for..in循环中。虽然诸如bar或baz之类的属性名称是可以枚举的,因为您能够从对象中进行console.log记录?
帕特里克

5
这并不完全正确:But, they are skipped (or not counted) by the for..in loop because they are not enumerableObject.prototype实际上,忽略这些属性是因为它们位于原型链的更上游,而不是因为它们不可枚举。无论是getOwnPropertyNames()keys()显示不是对象的自身属性。附带说明一下,确实有许多内置属性是不可枚举的,因此不会显示keys(),但是如果要遍历原型链,则必须编写额外的代码。
Magnus

从字面上看,无数意味着可数
克里斯蒂安·马修

49

如果通过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中的Non-enumerable属性,但显示了被枚举的对象。属性可以是可写,可配置或可枚举的,也可以是不可写的。John Resig在ECMAScript 5对象和属性的范围内对此进行了讨论。

而且,还有一个堆栈溢出问题,关于为什么您要使属性不可枚举


嗯,无论是赞成还是反对。当然,如果此答案有任何值得下注的地方,请在此处添加评论。
carpeliam

1
另一个答案是这样写的:var o = {}; o ['foo'] = 0; //可枚举的普通Object.defineProperty(o,'bar',{value:1}); //无数值,很奇怪为什么显式添加可枚举:false?
帕特里克

5
@Patrick,我在这里部分包括了它,以便从示例中清楚地知道它是一个选择,但是根据您的听众,明确地做出决定可以是一个可靠的决定,以便任何正在阅读您的代码的人都可以理解。
carpeliam

@carpeliam感谢您的简短说明,直到我
仔细

36

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

实际上,所有属性上都有一个称为“可枚举”的属性。如果将其设置为false,则该for..in方法将跳过该属性,并假装该属性不存在。

对象上有许多属性将“可枚举”设置为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”。


5
支持最后一行-我认为如果它实际上被称为forInAble,那么根本没有人会问它。这使我的问题-为什么你(或你为什么会得)的属性设置为不可枚举?数组的length属性经常被用作不可枚举属性的示例,但是为什么不能只将其设置为可枚举(不是JavaScript限制,我的意思是,为什么在JavaScript中将其设置为不可枚举)?第一名)?
克里斯

为了澄清我的问题,为什么决定不选择以下选项:制造商:本田车型:公民机密:猫尿尿长度:12
克里斯(Chris)

嗯...我可能已经找到了我自己问题的答案。在Google搜索中,“枚举数据类型是什么意思?” 枚举数据具有一组有限的值。枚举数据类型由您允许该类型的值或枚举值组成。对于基于整数的枚举类型,每个枚举值均由一个名称和一个基础数字值组成。因此,如果我正确理解,由于存在无限数量的可能长度,则必须分配无限数量的名称,一个名称每个长度。那是对的吗?
克里斯

好吧,解决您的第一个问题,在对象上设置不可枚举的属性有点棘手,因为您能够找出该对象上的内容的唯一方法是查看代码并作为代码库发展它可以被掩埋。因此,通常,您不想使用它。关于给出字符串中的字符数或数组中元素个数的'.length'只是假设,如果我们使用'for ... in',我们不希望包含在内。无法回答为什么Js的众神一定会那样做。他们的理由(啊哈超出了我们的理解)的意见。
加布里埃尔·昆克

...而且我认为我无法回答有关枚举数据类型的第二个问题,尽管如果有时间的话,我可能会想一会儿。:-)
Gabriel Kunkel 2015年

9

如果您难以想象“可枚举意味着什么?” 为什么不问自己,无数意味着什么呢?

我这样想,存在一个不可数的属性但部分被隐藏了;意思是,无数是奇怪的。现在您可以想象剩下的可以枚举了-自从发现对象以来我们曾经遇到的更自然的属性。考虑

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

现在在中for..in,将其想象为伪代码

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

您在JavaScript中键入的循环的主体位于/* whatever */


8

我将写一个ENUMERABLE的行定义

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

var obj = {};
Object.defineProperties(obj, {
    set1: {enumerable: true},
    set2: {enumerable: false},
});
Object.keys(obj); // ["set1"]
Object.getOwnPropertyNames(obj); // ["set1", "set2"]

0

方法不可枚举;在搜索了 Java脚本的可枚举含义之后,就没有了。它只是指向属性属性。.在ecma3中创建的所有对象都是可枚举的,并且ecma5现在可以定义它了。。就是这样。:D哈哈,我花了点时间找到答案;但是我相信它在David Flanagan的书中已经讨论过了。所以我想它的意思是“隐藏”,或者说不是“隐藏”,因为方法不会在for循环中显示,因此被“隐藏”了


0

考虑枚举数据类型,只是对应于不同数字的对象的结构。将某事物声明为可枚举就是声明该事物对应于特定数字,从而允许它在字典中被赋予代表对象的可数组成部分的位置。简单地说,使对象可枚举与告诉编译器相同:“嘿,这个属性很重要,当我检查该对象上的数据时,我希望看到它。”


0

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.