ECMAScript 5 有很多不错的补充。John Resig 在这里有一个很好的概述。这是一个很好的ECMAScript 5 兼容性表。
对于尚不支持这些功能的浏览器,很多这些东西可能是“伪造的”。你知道任何可以做到这一点的脚本吗?我对 Object.create 特别感兴趣。
例如,Douglas Crockford 的 JSON 脚本会在创建 JSON 函数之前检查它们是否存在。
如果有更多类似 JSON 的,我们可以在需要使用新函数时包含它们。
ECMAScript 5 有很多不错的补充。John Resig 在这里有一个很好的概述。这是一个很好的ECMAScript 5 兼容性表。
对于尚不支持这些功能的浏览器,很多这些东西可能是“伪造的”。你知道任何可以做到这一点的脚本吗?我对 Object.create 特别感兴趣。
例如,Douglas Crockford 的 JSON 脚本会在创建 JSON 函数之前检查它们是否存在。
如果有更多类似 JSON 的,我们可以在需要使用新函数时包含它们。
Crockford 推荐这种Object.create
垫片:
if (typeof Object.create != "function") {
Object.create = function (o) {
function F(){}
F.prototype = o;
return new F;
};
}
但请不要这样做。
这种方法的问题在于 ES5Object.create
有2 个参数的签名:第一个 - 要继承的对象,第二个(可选)- 表示要添加到新创建对象的属性(或者更确切地说,描述符)的对象。
Object.create(O[, Properties]); // see 15.2.3.5, ECMA-262 5th ed.
我们所拥有的是具有 2 种不同行为的不一致实现。在具有 native 的环境中Object.create
,方法知道如何处理第二个参数;在没有 native 的环境中Object.create
,它不会。
有哪些实际意义?
好吧,如果有一些代码(例如,第三方脚本)想要使用Object.create
,那么该代码执行此操作是相当合理的:
if (Object.create) {
var child = Object.create(parent, properties);
}
— 基本上假设如果Object.create
存在,它必须符合规范 — 接受第二个参数并向对象添加相应的属性。
但是,对于上述垫片,第二个参数被简单地忽略了。甚至没有迹象表明发生了什么错误的不同。可以说是无声的失败——检测和修复相当痛苦的事情。
我们能做得更好吗?
好吧,实际上不可能只使用(标准)ES3 工具来创建完全符合要求的Object.create
shim。最好的解决方案是创建一个自定义包装方法。
但是,您可以尝试的替代方法(不是最佳)很少:
1) 通知用户无法使用第二个参数
if (!Object.create) {
Object.create = function (o) {
if (arguments.length > 1) {
throw Error('second argument is not supported');
}
// ... proceed ...
};
}
2)尝试处理第二个参数:
if (!Object.create) {
Object.create = function (parent, properties) {
function F(){}
F.prototype = parent;
var obj = new F;
if (properties) {
// ... augment obj ...
}
return obj;
};
}
请注意,“属性”是一个表示属性描述符的对象,而不仅仅是属性名称/值,并且支持起来并不是很简单(有些事情甚至是不可能的,例如控制属性的可枚举性):
Object.create(parent, {
foo: {
value: 'bar',
writable: true
},
baz: {
get: function(){ return 'baz getter'; },
set: function(value){ return 'baz setter'; },
enumerable: true
}
});
原始 shim 中的另一个不一致之处是它不关心父对象是null
.
var foo = Object.create(null);
这将创建一个对象,其 [[Prototype]] 为null
; 换句话说,不从任何东西继承的对象,甚至不是Object.prototype
(ECMAScript 中的所有本机对象都继承自)。
foo.toString; // undefined
foo.constructor; // undefined
// etc.
顺便说一句,这对于在 ECMAScript 中创建“正确的”哈希表很有用。
可以模拟这种行为,但只能使用非标准扩展,例如“神奇” __proto__
属性(因此实现不是很便携或健壮)。这个问题的解决方案是类似的:要么完全模拟 ES5 实现,要么通知不一致/失败。
es5-shim http://github.com/kriskowal/es5-shim/
这是 narwhal 独立 javascript 环境的一部分,但已经独立出来了。它非常成熟和精确。
es5 - JavaScript/EcmaScript 5 in 3是在 BitBucket 上共享的集合。Object.create
特别是一个容易伪造的,由 Crockford等人制作,但由Justin Love改进,专注于许多 ES5 部分。
如果您不介意学习该库并自己编写一些代码,您可以在以下位置找到一些 ECMAScript 5 库的代码实现
https://developer.mozilla.org/En/JavaScript/ECMAScript_5_support_in_Mozilla
然后 Crockford 在 json2.js 中有 JSON.parse/stringify