【问题标题】:Is it possible to emulate non-enumerable properties?是否可以模拟不可枚举的属性?
【发布时间】:2012-02-13 15:19:21
【问题描述】:

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.prototype (Example)

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
  • 火狐3.6
  • Safari 4
  • Opera 11.5(Opera 11.6 解决了这个问题)。

ES5-shim 对此没有解决方案。

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

有没有什么黑魔法可以用专有的 IE 专用 API 来完成?也许用 VBScript?

【问题讨论】:

  • shim 可能永远无法实现这一点,因为for... in 的行为被硬连线到语言规范和解释器中。您要求的是不符合 ES5 的浏览器中不存在的东西。 +1 不过,您的问题总是很有趣。
  • @FrédéricHamidi 在看到上面链接的 VB 黑魔法之后,我不再那么确定了。
  • @FrédéricHamidi 我的知识说“这不可能”,但浏览器有很多奇怪的专有 API,这可能是可能的
  • 你试过traceur吗? code.google.com/p/traceur-compiler
  • @Tom traceur 如何提供帮助?我不知道怎么做。

标签: javascript internet-explorer ecmascript-5 emulation


【解决方案1】:

您可以通过代码重写来实现。将for (p in o) body的每次使用重写为

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

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

ES5/3 基本上就是这样做的。

【讨论】:

  • 是的,代码编译器是一种解决方案。不过,对于 ES5 合规性来说,这是一个丑陋的问题。顺便说一句,ES6/3 进展如何?
  • @Raynos,如果你认为在 ES3 上模拟属性属性很难,想象一下模拟 ephemeron 表 :)
  • 我仍然使用weakmap shim ;) 稍微容易一些。
  • @MikeSamuel:不要忘记测试以__notenum_ 开头的p - 那些__notenum_propname 属性也将是可枚举的!
【解决方案2】:

Jake VerbatenPartial.js 就是答案。

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);
        }
    }
};

我希望这对寻找此修复程序的人有所帮助。

【讨论】:

  • 这个问题是关于 ES3 的。我已经在问题中链接了我的实现,但它只适用于 ES5。
【解决方案3】:

如果你真的很关心 IE8/IE7 那么你可以这样做

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

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

接受的答案实际上不适用于文字,即字符串""、数字3 或布尔值true

【讨论】:

    猜你喜欢
    • 2015-05-16
    • 2011-12-22
    • 1970-01-01
    • 1970-01-01
    • 2013-09-03
    • 2012-05-03
    相关资源
    最近更新 更多