【问题标题】: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循环产生(对于那些不想知道细节或只是不关心的人;))跨度>

标签: javascript enumerable


【解决方案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 */ 的位置上

          【讨论】:

            猜你喜欢
            • 2017-01-27
            • 1970-01-01
            • 2011-06-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-09-05
            • 1970-01-01
            • 2012-07-31
            相关资源
            最近更新 更多