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

しかし、これをしないでください

このアプローチの問題は、ES5が2 つの引数Object.createの署名を持っていることです。1つ目は継承元のオブジェクト、2 つ目 (オプション) は、新しく作成されたオブジェクトに追加するプロパティ (または記述子) を表すオブジェクトです。

Object.create(O[, Properties]); // see 15.2.3.5, ECMA-262 5th ed.

私たちが持っているのは、2 つの異なる動作を持つ一貫性のない実装です。native のある環境ではObject.create、メソッドは 2 番目の引数の処理方法を知っています。nativeObject.createのない環境では、そうではありません。

実際的な意味は何ですか?

を使用したいコード (たとえば、サードパーティのスクリプト) がある場合Object.create、そのコードがこれを行うのはかなり合理的です。

if (Object.create) {
  var child = Object.create(parent, properties);
}

— 基本的に、存在する場合は仕様に準拠する必要があると仮定しObject.createます — 2 番目の引数を受け入れ、対応するプロパティをオブジェクトに追加します。

しかし、上記の shim では、2 番目の引数は単純に無視されます。何かが起こっている兆候すらありません違う違う。いわば静かな失敗 — 検出して修正するのはかなり面倒なことです。

もっとうまくやれるでしょうか?

(標準の) ES3 機能のみを使用して完全に準拠したシムを作成することは、Object.create実際には不可能です。最善の解決策は、カスタム ラッパー メソッドを作成することです。

ただし、試すことができる代替の (最適とは言えない) ものはほとんどありません。

1) 2 番目の引数を使用できないことをユーザーに通知する

if (!Object.create) {
  Object.create = function (o) {
    if (arguments.length > 1) { 
      throw Error('second argument is not supported'); 
    }
    // ... proceed ...
  };
}

2) 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/

これは、イッカクのスタンドアロン JavaScript 環境の一部でしたが、独自に分割されました。それはかなり成熟していて正確です。

于 2010-10-19T19:34:53.050 に答える
3

es5 - JavaScript/EcmaScript 5 in 3は、BitBucket で共有されているコレクションです。特に偽造Object.createしやすいもので、Crockfordらによって人気を博しましたが、多くの ES5 パーツに焦点を当てたJustin Loveによってここで改善されました。

于 2010-06-19T13:04:24.830 に答える
0

ライブラリの学習とコードの記述を気にしない場合は、ECMAScript 5 ライブラリのコード実装を次の場所で見つけることができます。

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

たとえば、Array.filterのコードは

そしてクロックフォードは json2.js に JSON.parse/stringify を持っています

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

于 2011-06-27T14:14:48.850 に答える