ES5中的Object.defineProperty?

时间:2010-09-30 13:11:26

标签: javascript ecma262 prototypal-inheritance ecmascript-5

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

我们是否坚持为旧的Object.create写作?我不能写一些在IE6 / 7中无效的东西。

3 个答案:

答案 0 :(得分:14)

在ECMAScript 3环境中,您无法通过ECMAScript 5 Object.create方法模拟一些事项。

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

@Raynos 提到的Object.defineProperty方法适用于IE8,但部分,可以在DOM中仅使用 元件。

此外,访问者属性会给您带来问题,可以模仿使用广泛支持的非标准方法,例如__defineGetter__ / __defineSetter__,但同样,你无法改变属性属性

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

这不能使用Crockford's Object.create shim进行模拟,因为当new运算符与构造函数一起使用时,prototype属性包含null - 或者任何其他非对象值 - 默认情况下,新创建的对象无论如何都会从Object.prototype继承。

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

我建议,如果您希望将旧浏览器作为目标,请不要使用这些功能,因为无法让它们在这些环境中正常运行。

如果您仍想使用Object.create,而不使用属性参数,则可以,但我建议您检测无法模拟的内容。

以下是Crockford's Object.create shim更安全的版本:

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

无论如何,请小心使用。

答案 1 :(得分:4)

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

不幸的是,您无法在ES3环境中配置枚举。此填充程序将允许您在任一环境中调用API,但在ES3下仍可以枚举属性。

答案 2 :(得分:2)

为了它的价值,

Object.defineProperty适用于ie8和FF4。

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

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

您必须解决在IE中使用dontEnum属性的方式。

[编辑]:

以下是Internet explorer的文档和ES5 specification的链接(第122页,15.2.3.6)