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

时间:2012-01-18 21:54:49

标签: javascript internet-explorer ecmascript-5 emulation

ES5有一个可枚举的标志。 Example

实施例

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

assert(pd.enumerable === false, "enumerability has the wrong value");

部分实施

Partial implementation可以让Object.keysObject.getOwnPropertyNames使用填充Object.defineProperty过滤掉新的非可枚举属性。

简介

这允许属性不可枚举。这显然意味着Example

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

这允许我们添加属性Object.prototypeExample

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]"

问题

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

Browser compat table

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

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

ES5-shim没有解决方法。

如果ES5垫片不起作用,则它有一个solution for most ES5 features that will break your code

是否有任何黑魔法可以通过仅限API的API使用?也许用VBScript?

3 个答案:

答案 0 :(得分:3)

您可以通过代码重写来完成。重写for (p in o) body

的每次使用
for (p in o) {
  if (!(/^__notenum_/.test(p) || o['__notenum_' + p])) {
    body
  } 
}

然后您可以通过定义__notenum_...属性来标记不可枚举的属性。要兼容,您必须调整上述内容,以确保__notenum_propnamepropname在同一原型级别定义,如果您使用它们,则覆盖eval和{{1}重写。

这基本上是ES5/3的作用。

答案 1 :(得分:-1)

Partial.jsJake Verbaten就是答案。

partial.js如下

/* partial non-enumerable property implementation

  Adds a flag to a weakmap saying on obj foo property bar is not enumerable.

  Then checks that flag in Object.keys emulation.
*/

// pd.Name :- https://github.com/Raynos/pd#pd.Name
var enumerables = pd.Name();

Object.defineProperty = function (obj, name, prop) {
    if (prop.enumerable === false) {
         enumerables(obj)[name] = true;
    }
    ...
};

Object.keys = function (obj) {
    var enumerabilityHash = enumerables(obj), keys = [];
    for (var k in obj) {
        if (obj.hasOwnProperty(k) && !enumerabilityHash[k]) {
             keys.push(k);
        }
    }
    return keys;
};

Object.getOwnPropertyNames = function (obj) {
    var keys = [];
    for (var k in obj) { 
        if (obj.hasOwnProperty(k)) {
             keys.push(k);
        }
    }
};

我希望这可以帮助那些寻找此修复程序的人。

答案 2 :(得分:-2)

如果您对IE8 / IE7非常关心,那么您可以

for (p in o) {
   if (o.hasOwnProperty(p)) { body } 
}

没有真正的“黑客”替代方案,但这可能是简单案例的解决办法

接受的答案对文字无效,即字符串"",数字3或布尔值true