5

私はES Harmony Symbol/ Namein ES5の実装を書いています。という名前を使用しますが、ブラウザーが既に存在する場合に備えて、Symbol既存のものを使用するようにします (将来のブラウザーで)。Symbolコードを ES5 に厳密に準拠させ、他のプロジェクトに移植できるようにしたいと考えています。

ES3 / ES5非厳密でやりたいことを行う(多くの)方法の1つを次に示します。

(function() {

    // If Symbol already exists, we're done.
    if(typeof Symbol != 'undefined') return;

    // This becomes global because it wasn't declared with var
    Symbol = function() {
        // ...
    };

})();

ただし、Symbol明示的に定義されていないため、ES5 の厳密な準拠ではありません。

windowこれを実現するには、オブジェクト ( ) にアクセスする必要がありますwindow.Symbol = ...が、コードがブラウザー環境で実行されることを想定したくないため、これも役に立ちません。

これは厳密なES5でどのように行うことができますか?

4

4 に答える 4

4

他のユーザーが投稿した回答から、同様の StackOverflow の質問にたどり着き、Google で検索して回答を見つけるための適切な用語が得られました。ソリューション:

最終的に、こちらで説明されている間接評価を使用して、この問題を解決することができました。

上記のリンク先の記事で詳しく説明されている間接 evalを使用すると、ES5 仕様に従ってグローバル スコープでコードが実行されます。ES5仕様に準拠し、パッケージマネージャーによって別の関数内であってもコードを文字通りどこにでもドロップでき、グローバルオブジェクトを見つけることができるため、私はこのアプローチを選択しました(提供された他の回答ではできませんでした) )。

解決策は、次のようなものです。

(function() {

    'use strict';

    var _global = (0, eval)('this');

    // If Symbol is already defined, there's nothing to do.
    if(_global.Symbol) return;

    _global.Symbol = function() {
        // ...
    };

})();

重要なのは、間接evalを使用してグローバル オブジェクトを取得することです (this間接のコンテキストでeval)。

これは、私が望んでいたように、最新のブラウザーや非ブラウザー環境を含め、ES5 に準拠したものであればすべて動作するはずです。

みんな助けてくれてありがとう!

eval唯一の注意点は、グローバル オブジェクトにアクセスするために、この間接的な方法 (今ではさらに悪いことです)を使用する必要がある (それは十分に悪いことです) のは少しハックに見えるということです。globalグローバルオブジェクトにアクセスするための識別子またはその他のメソッドは、仕様に含まれるべきではありませんか?

于 2012-10-12T04:03:24.337 に答える
1
'use strict';

var Symbol = 1; // try to comment this line and run the script again

var Symbol = (function(Symbol) {


    if(typeof Symbol != 'undefined') return Symbol;

    Symbol = function() {
        // ...
    };

    return Symbol;

})(Symbol);

alert(typeof Symbol);

</p>

http://jsfiddle.net/f0t0n/yATJW/

'use strict';

(function(g) { // g is a global context (this passed)

    if(typeof g.Array != 'undefined') {
        return;
    }

    g.Array = function() {
        // ...
    };

    g.Array.prototype.foo = function() {
        console.log('bar');
    };
})(this);

console.log(this.Array);​

http://jsfiddle.net/f0t0n/prwaP/

于 2012-10-11T22:29:45.437 に答える
1

なぜ匿名関数にする必要があるのですか?

// assuming global context
if (typeof this.Symbol === 'undefined') {
    this.Symbol = function () {
        // ...
    };
}

または関数で、ここでthis説明されているように渡します

(function (t) {
    if (typeof t.Symbol === 'undefined') {
        t.Symbol = function () {
            // ...
        };
    }
})(this);
于 2012-10-11T22:32:55.137 に答える
1

Symbol を追加するグローバル スコープを渡してはどうでしょうか。

(function(global){
 if(typeof global.Symbol != 'undefined') return;

    // This becomes global because it wasn't declared with var
    global.Symbol = function() {
        // ...
    };

})(window);  

これによりウィンドウに追加されますが、他のスコープまたは変数である可能性があります。

于 2012-10-11T22:33:40.063 に答える