可枚举是什么意思?

IT技术 javascript enumerable
2021-01-28 20:15:37

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

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

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

6个回答

可枚举属性是可以在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
从字面上看,enumerable 意味着可数
2021-03-15 20:15:37
所以构造函数属性是不可枚举的,因为它没有出现在 for..in 循环中。虽然 bar 或 baz 等属性的名称是可枚举的,因为您能够从对象中对每个属性进行 console.log 记录?
2021-03-18 20:15:37
@Magnus 他们使用的是for..in,而不是keys()for..in 确实遍历原型链,因此不可枚举是唯一将内置属性排除在外的方法。
2021-04-01 20:15:37
这并不完全正确:But, they are skipped (or not counted) by the for..in loop because they are not enumerable. on 的属性Object.prototype实际上被忽略了,因为它们位于原型链的更上游,而不是因为它们不可枚举。无论是getOwnPropertyNames()keys()显示不是对象的自身属性。作为旁注,许多内置属性确实不可枚举,因此不会显示 with keys(),但是如果要遍历原型链,则必须编写额外的代码。
2021-04-07 20:15:37

如果您通过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 对象和属性的范围内讨论了这一点

并且,有一个 Stack Overflow 问题,关于为什么您想要使属性不可枚举

@carpeliam 感谢这个简短而清晰的解释,直到我通过你的回答,我才能得到接受:D
2021-03-29 20:15:37
@Patrick,我将它部分包含在此处,以便从示例中清楚地表明它是一个选项,但根据您的受众,明确可能是一个可靠的决定,以便任何阅读您代码的人都清楚。
2021-04-01 20:15:37
另一个答案写道: var o = {}; o['foo'] = 0; // 可枚举,普通 Object.defineProperty(o, 'bar', {value: 1}); // 不可枚举,很奇怪 为什么要显式添加 enumerable: false?
2021-04-04 20:15:37
嗯,赞成和反对。当然,如果这个答案有任何值得否决的地方,请在此处添加评论。
2021-04-08 20:15:37

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

从字面上看,所有属性上都有一个称为“可枚举”的属性。当它设置为 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”。

好吧,解决您的第一个问题,在对象上设置不可枚举的属性有点麻烦,因为您能够找出该对象上的内容的唯一方法是查看代码并将其作为代码库发展它可以被掩埋。所以,一般来说,你不会想使用它。关于给出字符串中的字符数或数组中的元素数的 '.length' 只是假设我们不希望包含的东西,如果我们使用 'for... in'。无法回答为什么 Js 的众神一定会这样做。他们有我们无法理解的理由(咳咳)意见。
2021-03-22 20:15:37
嗯...我可能已经找到了我自己问题的答案。从谷歌搜索“枚举数据类型是什么意思?” 枚举数据具有一组有限的值。枚举数据类型由您允许用于该类型的值或枚举值组成。对于基于整数的枚举类型,每个枚举值都由一个名称和一个基础数值组成。所以,如果我理解正确的话,由于可能的长度有无数个,因此您必须分配无数个名称,一个名称到每个长度。那是对的吗?
2021-03-28 20:15:37
赞成最后一行 - 我认为如果它真的被称为 forInAble 根本没有人会问它。这使我的问题-为什么你(或你为什么会得)的属性设置为不可枚举?数组的长度属性经常被用作不可枚举属性的示例,但是为什么不能将其设置为可枚举(不是 JavaScript 限制,我的意思是,为什么在 JavaScript 中将其设置为不可枚举?第一个)?
2021-03-30 20:15:37
...而且我认为我无法回答您关于枚举数据类型的第二个问题,尽管如果我有时间的话,它看起来像是我可以咀嚼很长时间的东西。:-)
2021-03-30 20:15:37
为了澄清我的问题,为什么决定以下不是一个选项:制造:本田型号:公民秘密:猫尿长度:12
2021-04-06 20:15:37

我将编写ENUMERABLE 的一行定义

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

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

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

我觉得有点像这样,一个不可枚举的属性存在但部分隐藏这意味着不可枚举是奇怪的。现在您可以将 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 */