我看到有关于一个“新”的Object.create的帖子,它使枚举可配置。但是,它依赖于Object.defineProperty方法。我找不到这个方法的跨浏览器实现。
我们是否只能使用旧版的Object.create?我不能写那些在IE6/7中无法工作的代码。
我看到有关于一个“新”的Object.create的帖子,它使枚举可配置。但是,它依赖于Object.defineProperty方法。我找不到这个方法的跨浏览器实现。
我们是否只能使用旧版的Object.create?我不能写那些在IE6/7中无法工作的代码。
在 ECMAScript 3 环境中,有一些东西是无法从 ECMAScript 5 的 Object.create
方法中模拟出来的。
正如你所看到的,由于 E3 实现中没有办法更改属性特性,因此属性参数会给你带来问题。
@Raynos 提到的 Object.defineProperty
方法在 IE8 中可以使用,但只能在 DOM 元素中部分地使用。
另外,访问器属性也会给你带来问题。它们可以使用广泛支持的非标准方法(如__defineGetter__
/__defineSetter__
)进行模拟,但同样地,你无法更改属性特性。
除了属性描述符之外,另一个问题是 Object.create
方法可以接受 null
作为参数,以创建一个不从任何对象继承的对象。
这不能用Crockford's Object.create
shim来模拟,因为当使用具有包含null
或其他非对象值的 prototype
属性的构造函数与 new
运算符一起创建新对象时,新创建的对象将默认继承自 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;
};
})();
}
无论如何,要小心使用它。
值得一提的是,Object.defineProperty 在ie8和FF4中可用。
这意味着在有用的地方进行功能嗅探并实现它是值得的,因为您希望从ie 6/7升级到8/9将在未来几年内发生。
还要注意的另一件事是,dontEnum属性在JScript中存在错误。
您将不得不解决在IE中使用dontEnum属性的方式。
[编辑]:
这里是Internet explorer的文档和ES5规范链接(第122页,15.2.3.6)。
Object.defineProperty
在IE8上只能部分使用,只能用于DOM元素。我在答案中简要地说了一下:你不能这么做。属性描述符无法在基于ECMAScript 3的实现中定义... - Christian C. Salvadó