ES5 中的 Object.defineProperty?

IT技术 javascript ecma262 prototypal-inheritance ecmascript-5
2021-02-18 20:17:55

我看到有关“新” Object.create 的帖子,它使枚举可配置。但是,它依赖于 Object.defineProperty 方法。我找不到此方法的跨浏览器实现。

我们是否在为旧的 Object.create 编写代码?我不能写在 IE6/7 中不起作用的东西。

3个回答

Object.createECMAScript 3 环境中,您无法从 ECMAScript 5方法中模拟一些事情

如您所见,properties 参数会给您带来问题,因为在基于 E3 的实现中,无法更改属性属性。

@Raynos提到Object.defineProperty方法适用于 IE8,但部分地,它只能在 DOM 元素中使用。

此外,访问器属性会给您带来问题,它们可以被广泛支持的非标准方法(例如/ )模仿,但同样,您无法更改属性 attributes__defineGetter____defineSetter__

除了属性描述符之外的另一个问题是,该Object.create方法可以接受null作为参数,以创建不从任何继承的对象。

这不能用Crockford 的Object.createshim模拟,因为当new运算符与具有prototype包含null- 或任何其他非对象值属性的构造函数一起使用Object.prototype,默认情况下,新创建的对象将从任何地方继承

在某些实现中 -V8、Spidermonkey、Rhino 等... - 它们具有__proto__可用于设置null[[Prototype]] 的可设置属性,但同样,这是非标准的,并且肯定它永远不会在 IE 上工作.

我会建议,如果您想针对旧浏览器不使用这些功能,因为没有办法让它们在这些环境中正常工作。

如果您仍然想使用Object.create, 而不使用properties参数,您可以,但是我建议您检测无法模拟的东西。

以下是Crockford垫片更安全版本Object.create

if (typeof Object.create != 'function') {
  (function () {
    var F = function () {};
    Object.create = function (o) {
      if (arguments.length > 1) { throw Error('Second argument not supported');}
      if (o === null) { throw Error('Cannot set a null [[Prototype]]');}
      if (typeof o != 'object') { throw TypeError('Argument must be an object');}
      F.prototype = o;
      return new F;
    };
  })();
}

总之,慎用。

如果你想要一个好的 defineProperty() 实现,看看https://github.com/kriskowal/es5-shim

不幸的是,您无法在 ES3 环境中使枚举可配置。此 shim 可让您在任一环境中调用 API,但在 ES3 下仍可枚举属性。

物有所值,

Object.defineProperty适用于 ie8 和 FF4。

这意味着值得使用嗅探功能并在有用的地方实施它,因为您希望在未来几年内从 ie 6/7 升级到 8/9。

另一件需要注意的事情是 dontEnum 属性在JScript 中有一个错误

您将不得不解决在 IE 中使用 dontEnum 属性的方式。

[编辑]:

这是Internet Explorer的文档ES5 规范的链接(第 122 页,15.2.3.6)

@Drew:Object.defineProperty工程部分IE8,你可以用它只能在DOM元素我留下了一个答案,简而言之:你不能。无法在基于 ECMAScript 3 的实现上定义属性属性....
2021-04-28 20:17:55
很高兴知道它在 IE8 中,我看到了可能是一个实现的一瞥。所以,我的问题仍然是有一个已发布的defineProperty 实现吗?
2021-04-29 20:17:55
我什至没有注意到它只适用于 DOM 元素。感谢您指出了这一点。
2021-05-13 20:17:55
ie6/7 恐怕没有这样的实现。
2021-05-15 20:17:55