【发布时间】:2011-04-19 08:24:48
【问题描述】:
我看到了有关“新”Object.create 的帖子,它使枚举可配置。但是,它依赖于 Object.defineProperty 方法。我找不到此方法的跨浏览器实现。
我们是否还在为旧的 Object.create 编写代码?我无法编写在 IE6/7 中不起作用的东西。
【问题讨论】:
标签: javascript ecma262 prototypal-inheritance ecmascript-5
我看到了有关“新”Object.create 的帖子,它使枚举可配置。但是,它依赖于 Object.defineProperty 方法。我找不到此方法的跨浏览器实现。
我们是否还在为旧的 Object.create 编写代码?我无法编写在 IE6/7 中不起作用的东西。
【问题讨论】:
标签: javascript ecma262 prototypal-inheritance ecmascript-5
在 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 [[Prototype]],但同样,这是非标准的,并且肯定它永远不会在 IE 上运行。
如果您想让旧浏览器不使用这些功能,我建议您不要使用这些功能,因为没有办法让它们在这些环境中正常工作。
如果你仍然想使用Object.create,而不使用properties 参数,你可以,但是我建议你检测无法模拟的东西。
以下是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;
};
})();
}
无论如何,请谨慎使用。
【讨论】:
如果您想要一个好的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 specification 的链接(第 122 页,15.2.3.6)
【讨论】:
Object.defineProperty 部分 IE8,你只能在DOM元素上使用它。我留下了answer,简而言之:你不能。属性属性不能在基于 ECMAScript 3 的实现上定义......