可枚举的意思是什么?

Pat*_*ick 142 javascript enumerable

当它说"for..in迭代一个对象的可枚举属性时,我被引导到MDN for..in页面."

然后我进入了属性页Enumerability和owner,它说"可枚举的属性是那些可以通过for..in循环迭代的属性".

字典将可枚举定义为可数,但我无法真实地想象这意味着什么.我可以得到一些可枚举的例子吗?

Jon*_*ski 142

可枚举属性是可以在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"
Run Code Online (Sandbox Code Playgroud)

属性通过其自己的[[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 }
Run Code Online (Sandbox Code Playgroud)

for..in则遍历对象的属性名称进行迭代.

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

for (var prop in foo)
    console.log(prop); // outputs 'bar' and 'baz'
Run Code Online (Sandbox Code Playgroud)

但是,仅console.log(prop);针对属性为的[[Enumerable]]属性评估其语句(在本例中)true.

这种情况已经到位,因为对象具有更多属性,尤其是继承:

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

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

console.log('constructor' in foo); // true
console.log('toString' in foo);    // true
// etc.
Run Code Online (Sandbox Code Playgroud)

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

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

console.log(descriptor.enumerable); // false
Run Code Online (Sandbox Code Playgroud)

  • 这不完全正确:`但是,它们被for..in循环跳过(或不计算),因为它们不是可枚举的."Object.prototype"上的属性实际上被忽略了,因为它们在原型链的上游,而不是因为它们不是可枚举的.`getOwnPropertyNames()`或`keys()`都不显示不属于对象的属性.作为旁注,确实许多内置属性不是可枚举的,因此不会用`keys()`显示,但如果你想遍历原型链,你将不得不编写额外的代码. (5认同)
  • @Magnus他们使用的是`for..in`,而不是`keys()`。`for..in` **确实**遍历原型链,因此不可枚举是唯一保留内置属性的方法。 (2认同)

car*_*iam 47

如果您通过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'
Run Code Online (Sandbox Code Playgroud)

此示例大量借用JavaScript中的非可枚举属性,但显示了枚举的对象.属性可以是可写的,也可以是可配置的,也可以是可枚举的.John Resig在ECMAScript 5对象和属性的范围内对此进行了讨论.

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

  • @Patrick,我将其部分包含在这里,以便从示例中清楚地看出它是一个选项,但是根据您的受众,明确可以是一个可靠的决定,以便任何正在阅读您的代码的人都清楚. (5认同)

Gab*_*kel 34

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

字面上,所有属性都有一个名为"enumerable"的属性.当它设置为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
  });
Run Code Online (Sandbox Code Playgroud)

现在,隐藏着关于汽车甚至秘密的事实.当然,他们仍然可以直接访问该物业并获得答案:

console.log(car.mySecretAboutTheCar); // prints 'cat pee in back seat'
Run Code Online (Sandbox Code Playgroud)

但是,他们必须首先知道该属性存在,因为如果他们试图通过它for..inObject.keys它将保持完全秘密:

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

他们本应该称它为"forInAble".

  • 为最后一行投票 - 我认为如果它实际上被称为InAble,根本没有人会问它.这提出了我的问题 - 为什么_would_你(或为什么你必须)设置一个不可枚举的属性?数组的length属性经常被用作非可枚举属性的一个例子,但为什么你不能将它设置为可枚举(不是JavaScript限制,我的意思是,为什么它设置为不能在JavaScript中枚举第一名)? (5认同)

Pau*_* S. 9

如果您难以想象"可枚举的意义是什么?" 为什么不问问自己,无数是什么意思?

我认为它有点像这样,存在一个不可数的属性但是部分隐藏 ; 意思是无数是奇怪的.现在你可以想象剩下的东西 - 自从我们发现对象以来我们习惯遇到的更自然的属性.考虑

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

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

for property in o:
    if not property enumerable continue // skip non-enumerable, "bar"
    else do /* whatever */              // act upon enumerable, "foo"
Run Code Online (Sandbox Code Playgroud)

你用JavaScript键入的循环体是代替的/* whatever */


Ved*_*Ved 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"]
Run Code Online (Sandbox Code Playgroud)