16

ECMAScript 5 有很多不错的补充。John Resig 在这里有一个很好的概述。这是一个很好的ECMAScript 5 兼容性表

对于尚不支持这些功能的浏览器,很多这些东西可能是“伪造的”。你知道任何可以做到这一点的脚本吗?我对 Object.create 特别感兴趣。

例如,Douglas Crockford 的 JSON 脚本会在创建 JSON 函数之前检查它们是否存在。

如果有更多类似 JSON 的,我们可以在需要使用新函数时包含它们。

4

4 回答 4

40

Crockford 推荐这种Object.create垫片:

if (typeof Object.create != "function") {
  Object.create = function (o) {
    function F(){}
    F.prototype = o;
    return new F;
  };
}

但请不要这样做

这种方法的问题在于 ES5Object.create2 个参数的签名:第一个 - 要继承的对象,第二个(可选)- 表示要添加到新创建对象的属性(或者更确切地说,描述符)的对象。

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.createshim。最好的解决方案是创建一个自定义包装方法。

但是,您可以尝试的替代方法(不是最佳)很少:

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 实现,要么通知不一致/失败。

于 2010-06-19T14:28:18.367 回答
8

es5-shim http://github.com/kriskowal/es5-shim/

这是 narwhal 独立 javascript 环境的一部分,但已经独立出来了。它非常成熟和精确。

于 2010-10-19T19:34:53.050 回答
3

es5 - JavaScript/EcmaScript 5 in 3是在 BitBucket 上共享的集合。Object.create特别是一个容易伪造的,由 Crockford等人制作,但由Justin Love改进,专注于许多 ES5 部分。

于 2010-06-19T13:04:24.830 回答
0

如果您不介意学习该库并自己编写一些代码,您可以在以下位置找到一些 ECMAScript 5 库的代码实现

https://developer.mozilla.org/En/JavaScript/ECMAScript_5_support_in_Mozilla

例如Array.filter的代码

然后 Crockford 在 json2.js 中有 JSON.parse/stringify

https://github.com/douglascrockford/JSON-js

于 2011-06-27T14:14:48.850 回答