可枚举是啥意思?

Posted

技术标签:

【中文标题】可枚举是啥意思?【英文标题】:What does enumerable mean?可枚举是什么意思? 【发布时间】:2013-07-27 10:52:50 【问题描述】:

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

然后我去了Enumerability and ownership of properties page,它说“可枚举的属性是那些可以通过 for..in 循环迭代的属性。”

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

【问题讨论】:

你明白for-in是做什么的吗? 从我得到的答案中,for..in 允许对象的所有可枚举属性都可用于 for 语句 最简单的意思是:一个属性是否会由for in循环产生(对于那些不想知道细节或只是不关心的人;))跨度> 【参考方案1】:

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

【讨论】:

【参考方案2】:

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

【讨论】:

【参考方案3】:

我会写一行ENUMERABLE

的定义

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

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

【讨论】:

【参考方案4】:

可枚举属性是可以在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]] attribute 标识为可枚举或不可枚举。您可以将其视为property's descriptor 的一部分:

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的属性。

这个条件成立是因为对象have many more properties,尤其是from inheritance:

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

这些属性中的每一个仍然是exists on the object:

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 等属性的名称是可枚举的,因为您可以从对象中控制台记录每一个? 这并不完全正确:But, they are skipped (or not counted) by the for..in loop because they are not enumerableObject.prototype 上的属性实际上被忽略了,因为它们位于原型链的更上游,而不是因为它们不可枚举。 getOwnPropertyNames()keys() 都不显示不属于对象的属性。附带说明一下,确实许多内置属性是不可枚举的,因此不会在 keys() 中显示,但如果您想遍历原型链,则必须编写额外的代码。 字面意思,可枚举的意思是可数的 @Magnus 他们使用的是for..in,而不是keys()for..in 确实遍历原型链,因此不可枚举是唯一将内置属性排除在外的事情。【参考方案5】:

这比应该可视化的东西无聊多了。

实际上所有属性都有一个属性,称为“可枚举”。当它设置为 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..inObject.keys 访问它,它将完全保密:

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

他们应该叫它“forInAble”。

【讨论】:

赞成最后一行 - 我认为如果它真的被称为 forInAble 没有人会问这个问题。这提出了我的问题 - 为什么您(或为什么必须)将属性设置为不可枚举?数组的长度属性经常被用作不可枚举属性的示例,但是为什么不能将其设置为可枚举(不是 JavaScript 限制,我的意思是,为什么在 JavaScript 中将其设置为不可枚举?第一名)? 为了澄清我的问题,为什么决定以下选项不是一个选项:品牌:本田车型:思域秘密:猫尿长度:12 嗯...我可能已经找到了自己问题的答案。从谷歌搜索“枚举数据类型是什么意思?”枚举数据具有一组有限的值。枚举数据类型由您允许该类型使用的值或枚举值组成。对于基于整数的枚举类型,每个枚举值都由一个名称和一个基础数值组成。所以,如果我理解正确,由于可能的长度是无限的,因此您必须分配无限数量的名称,一个名称到每个长度。对吗? 好吧,解决您的第一个问题,在对象上设置不可枚举的属性有点笨拙,因为您能够找出该对象上的内容的唯一方法是查看在代码中,随着代码库的发展,它可能会被掩埋。所以,一般来说,你不想使用它。关于“.length”,它给出了字符串中的字符数或数组中的元素,假设我们不希望包含在使用“for ... in”时。无法回答为什么 Js 的众神一定会那样做。他们有我们无法理解的理由(ahem)意见。 ...我不认为我可以回答您关于枚举数据类型的第二个问题,尽管如果我有时间的话,我可以仔细研究一段时间。 :-)【参考方案6】:

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

【讨论】:

【参考方案7】:

如果您通过myObj = foo: 'bar' 或类似的方式创建对象,则所有属性都是可枚举的。所以更容易问的问题是,什么是不可枚举的?某些对象有一些不可枚举的属性,例如如果你调用Object.getOwnPropertyNames([])(它返回一个包含所有属性的数组,无论是否可枚举,on []),它会返回['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'

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

还有一个关于 why you'd ever want to make properties non-enumerable 的 Stack Overflow 问题。

【讨论】:

嗯,赞成票和反对票。当然,如果这个答案有什么值得反对的地方,请在此处添加评论。 另一个答案是这样写的:var o = ; o['foo'] = 0; // 可枚举,普通 Object.defineProperty(o, 'bar', value: 1); // 不可枚举,奇怪 为什么要显式添加 enumerable: false? @Patrick,我将其部分包含在此处,以便从示例中清楚地看出这是一个选项,但取决于您的受众,明确可能是一个可靠的决定,这样任何人都可以清楚阅读您的代码。 @carpeliam 感谢您的简短而清晰的解释,直到我通过您的回答我才能得到接受的答案:D【参考方案8】:

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

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

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 */ 的位置上

【讨论】:

以上是关于可枚举是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

Java里的包,类,接口,枚举是啥意思

C#中的“对象被枚举”是啥意思?

Java 枚举类型中受保护的变量是啥意思? [复制]

C语言枚举类型是啥意思?

enum在java中是啥意思

java中的枚举是啥意思?