8

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

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

4

3 回答 3

14

Object.create在ECMAScript 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;
    };
  })();
}

无论如何,小心使用它。

于 2010-10-02T07:19:05.900 回答
4

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

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

于 2011-04-03T18:36:28.323 回答
2

物有所值,

Object.defineProperty适用于 ie8 和 FF4。

这意味着它值得特色嗅探并在有用的地方实现它,因为您希望从 ie 6/7 升级到 8/9 将在未来几年内发生。

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

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

[编辑]:

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

于 2010-09-30T14:31:16.000 回答