可枚举是啥意思?
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 enumerable
。 Object.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..in
或Object.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 */
的位置上
【讨论】:
以上是关于可枚举是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章