是否可以模拟不可枚举的属性?

Ray*_*nos 31 javascript internet-explorer emulation ecmascript-5

ES5有一个可枚举的标志.

var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor
 , pd = getOwnPropertyDescriptor(Object.prototype, "toString");

assert(pd.enumerable === false, "enumerability has the wrong value");
Run Code Online (Sandbox Code Playgroud)

部分实施

通过使用shimmed来获取Object.keysObject.getOwnPropertyNames过滤掉新的非可枚举属性,可以实现部分实现Object.defineProperty.

介绍

这允许属性不可枚举.这显然意味着实例

for (var key in {}) {
    assert(key !== "toString", "I should never print");
}
Run Code Online (Sandbox Code Playgroud)

这允许我们添加属性来说Object.prototype(例子)

Object.defineProperty(Object.prototype, "toUpperCaseString", {
    value: function toUpperCaseString() {
        return this.toString().toUpperCase();
    },
    enumerable: false
});

for (var key in {}) {
    assert(key !== "toUpperCaseString", "I should never print");
}

console.log(({}).toUpperCaseString()); // "[OBJECT OBJECT]"
Run Code Online (Sandbox Code Playgroud)

我们如何在非ES5兼容的浏览器中模拟这一点?

浏览器compat表

在这种情况下,我们关心可能解决这个问题

  • IE <9(IE8仅适用于DOM对象)
  • Firefox 3.6
  • Safari 4
  • Opera 11.5(Opera 11.6解决了这个问题).

ES5-垫片没有一个解决方案.

ES5垫片大多数 ES5功能提供解决方案,如果它不起作用将会破坏您的代码.

是否有任何黑魔法可以使用仅限临时IE的API来完成?也许用VBScript?

Mik*_*uel 3

您可以通过代码重写来做到这一点。for (p in o) body重写to的每个用法

for (p in o) {
  if (!(/^__notenum_/.test(p) || o['__notenum_' + p])) {
    body
  } 
}
Run Code Online (Sandbox Code Playgroud)

然后您可以通过定义__notenum_...属性来标记不可枚举的属性。为了兼容,您必须调整上面的内容,以确保 与__notenum_propname定义在相同的原型级别propname,并且如果您使用它们,请覆盖evalnew Function重写。

这基本上就是ES5/3所做的事情。