使属性不可枚举有什么好处?

Ans*_*hul 45 javascript prototype enumerable

可枚举性是属性的三个属性之一:可写性,可枚举性和可配置性.我的问题是:

  • 在JavaScript中使属性不可枚举有什么好处?我知道我们通过使它们不可枚举来隐藏财产,但财产隐藏的好处是什么?
  • 我们可以访问不可枚举的属性吗?如果是,那么使它们不可枚举的好处是什么?
  • 对象的所有预定义属性是否都设置为不可枚举?例如Array的属性poppush属性是不可枚举的?

Ian*_*Ian 40

我认为主要的好处是能够控制在枚举对象的属性时显示的内容,例如for inObject.keys().

MDN解释得很好Object.defineProperty:https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty

通常情况下,当人们想要添加方法时Object,例如对于旧浏览器不支持的某种方法的polyfill,他们会修改.prototype.但是这使得属性可以枚举并且弄乱了循环/键集合中返回的内容(不使用.hasOwnProperty ...不是每个人都使用的).

所以,而不是像:

Object.prototype.myMethod = function () {
    alert("Ahh");
};
Run Code Online (Sandbox Code Playgroud)

你可以Object.defineProperty用来明确地说它不是可枚举的:

Object.defineProperty(Object.prototype, 'myMethod', {
    value: function () {
        alert("Ahh");
    },
    enumerable: false
});
Run Code Online (Sandbox Code Playgroud)

这样,例如当你使用时for (var key in obj),"myMethod"将不是枚举的项目,你不必担心使用.hasOwnProperty.这个问题的主要问题是有些浏览器当然不支持它:http://kangax.github.com/es5-compat-table/并不是所有的库/代码都使用它,所以你不能总是依赖它在外部库/代码上做正确和一直使用.

您可以随时访问不可枚举的属性,在枚举对象的属性时它不会显示 - 这是主要观点.

而且我确实认为对象的所有"预定义"属性都是不可枚举的.通过这个,我真的只是意味着本机属性,不一定是继承或创建的.所以,你的榜样,pop并且push被过度列举,但Array.prototype.indexOf如果它是作为一个古老的浏览器不支持该方法......这当然,可以通过使用避免填充工具创建的将是Object.defineProperty像我上面的例子.另一个例子是length属性,没有列举.

这是一般的例子:http://jsfiddle.net/aHJ3g/

使用和定义Object.keys很重要:"返回给定对象自己的可枚举属性的数组,其顺序与for-in循环提供的顺序相同(不同之处在于for-in循环枚举原型链中的属性)." - 来自MDN - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys


Gar*_*ang 12

我认为另一个主要好处是它可以防止对象的私有属性污染公共命名空间.

假设您已创建并发布了一个名为的强大库Cosmos.用户激活Node解释器并通过调用构造函数创建它的新实例:

var Cosmos = require('Cosmos');
var cosmos = new Cosmos('my empire');
Run Code Online (Sandbox Code Playgroud)

现在,用户只需键入cosmos并按Enter即可查看它支持的公共API.您希望用户看到哪两个?

{ name: 'my empire',
  grow: [Function: grow],
  addStar: [Function: addStar],
  beautify: [Function: beautify],
  implode: [Function: implode],
  destroy: [Function: destroy] }
Run Code Online (Sandbox Code Playgroud)

要么

{ _age: 25000,
  _size: 35000,
  _destroyed: false,
  name: 'my empire',
  _numStars: 200,
  _init: [Function: _init],
  grow: [Function: grow],
  _grow: [Function: _grow],
  addStar: [Function: addStar],
  _checkStatus: [Function: _checkStatus],
  beautify: [Function: beautify],
  implode: [Function: implode],
  destroy: [Function: destroy] }
Run Code Online (Sandbox Code Playgroud)

  • 不可枚举的属性仍然是公共的,仍然会污染命名空间.如果你想要私人财产,你需要一个闭包. (5认同)
  • 我赞同答案和评论.评论的批评在我看来是有效的,所以也许回答者使用"公共"和"私人"可能不是最佳的.但是,我认为答案的重点仍然有用(至少对我而言)因为它显示了可枚举性如何帮助库用户更容易地看到库作者希望库用户轻松使用的内容(例如,请使用`成长而不是`_grow`,即使两者在技术上仍然是公开的). (4认同)