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

发布于 2024-12-27 18:09:29 字数 1699 浏览 0 评论 0原文

ES5 有一个可枚举标志。 示例

示例

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

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

部分实现

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

简介

这允许属性是不可枚举的。这显然意味着 示例

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

这允许我们添加属性来表示 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]"

问题

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

浏览器兼容表

在这种情况下,我们关心的是可能为

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

ES5-shim 没有针对此问题的解决方案。

ES5 shim 有一个针对大多数 ES5 功能的解决方案,如果它不起作用,将会破坏您的代码

是否有任何黑魔法可以通过仅适用于 IE 的 API 来完成?也许用 VBScript ?

ES5 has a enumerable flag. Example

Example

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

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

Partial implementation

Partial implementation is do-able by having Object.keys and Object.getOwnPropertyNames filter out new non-enumerable properties using the shimmed Object.defineProperty.

Introduction

This allows for properties to be non enumerable. This clearly means that Example

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

This allows us to add properties to say 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]"

Question

How can we emulate this in non-ES5 compliant browsers?

Browser compat table

In this case we care about potentially solving this for

  • IE < 9 (IE8 only works on DOM objects)
  • Firefox 3.6
  • Safari 4
  • Opera 11.5 (Opera 11.6 solves this).

The ES5-shim does not have a solution for this.

The ES5 shim has a solution for most ES5 features that will break your code if it doesn't work.

Is there any black magic that can be done with propiotory IE only APIs? Maybe with VBScript?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

久夏青 2025-01-03 18:09:29

您可以通过代码重写来做到这一点。将 for (p in o) body 的每次使用重写为

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

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

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

You can do it via code-rewriting. Rewrite every use of for (p in o) body to

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

and then you can mark properties not enumerable by defining a __notenum_... property. To be compatible you would have to tweak the above to make sure that __notenum_propname is defined at the same prototype level as propname, and if you use them, overwrite eval and new Function to rewrite.

That's basically what ES5/3 does.

温暖的光 2025-01-03 18:09:29

Partial.js 作者:Jake 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);
        }
    }
};

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

Partial.js by Jake Verbaten is the answer to it.

The partial.js is as follows

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

I hope this helps the guys searching for this fix.

も星光 2025-01-03 18:09:29

如果您确实非常关心 IE8/IE7 那么您可以这样做

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

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

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

If you do care a lot about IE8/IE7 then you can do

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

There is no real "hack" alternative but this could be a work-around for simple cases

The accepted answer doesn't really work for literals i.e. strings "", numbers 3, or booleans true

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文