6

global次のように、JavaScriptでオブジェクトを1行で定義しようとしています。

var global = this.global || this;

上記のステートメントはグローバルスコープにあります。したがって、ブラウザでは、thisポインタはwindowオブジェクトのエイリアスです。現在のWebページのコンテキストで実行されるJavaScriptの最初の行であると仮定すると、の値は常にポインターまたはオブジェクトの値globalと同じになります。thiswindow

RingoJSやnode.jsなどのCommonJS実装では、thisポインターは現在のを指しますModuleScope。ただし、で定義されたglobalプロパティを介してオブジェクトにアクセスできます。したがって、プロパティを介してアクセスできます。globalModuleScopethis.global

したがって、このコードスニペットはすべてのブラウザーで機能し、少なくともRingoJSとnode.jsで機能しますが、他のCommomJS実装はテストしていません。したがって、このコードを他のCommonJS実装で実行したときに正しい結果が得られないかどうか、またそうであれば、どのように修正できるかを知りたいと思います。

最終的には、実装に依存しないJavaScriptフレームワークのラムダ式で次のように使用する予定です(jQueryのアイデア)。

(function (global) {
    // javascript framework
})(this.global || this);
4

3 に答える 3

5

thisスコープとはまったく関係ありません。

(function(){
    (function(){
        (function(){

            (function(){
            alert( this ); //global object
            })()

        }).bind({})()
    }).apply({})
}).call({})

this関数の呼び出し時にのみ解決され、いくつかの単純なルールになります。

  1. 関数がオブジェクトのプロパティとして呼び出された場合、そのオブジェクトはthis関数内にあります
  2. 関数がそのまま呼び出された場合、はthis未定義になるため、非厳密モードではグローバルオブジェクトになります
  3. 関数がで呼び出された場合、.call/.applyそれthisは自分で明示的に設定されます。

ご覧のとおり、ルール#2に該当し、に解決されundefinedます。そしてないので"use strict";

ThisBindingをグローバルオブジェクトに設定します

編集:私はRingoJSでいくつかの簡単なテストを実行しましたが、実際には「グローバルオブジェクト」を実際のグローバルオブジェクト(標準で定義されている)の中に入れていますModuleScope。ほとんどのjs実装の実際のグローバルオブジェクトにObjectやStringなどがあるからといって、それらのオブジェクトがその下にある場合、オブジェクトはグローバルになりません。StringRingoJSにアクセスできる理由Objectは、それらがModuleScopeプロトタイプに組み込まれているためです。

var logs = require('ringo/logging').getLogger("h");

logs.info( Object.getPrototypeOf( this ) === this.global );
//true

ModuleScope実際のグローバルオブジェクトであるさらなる証拠:

this.property = "value";
logs.info( property );
//"value"

したがって、この種のトリックからは何も得られず、何も修正されません。

function injectGlobal(){
globalProperty = "value"; // "use strict" would fix this!
}

injectGlobal()

logs.info( globalProperty );
//"value"

Rant overはthis、この投稿の前半で示したルールに従ってすでに実際のグローバルオブジェクトを指します。this.global標準で定義されている実際のグローバルオブジェクトではなく、単なるコンテナです。

さらに、ブラウザでこの動作をエミュレートできます。

scopehack.jsを検討してください

this.global = window.global || top.global || {};

main.htmlを検討してください。

<script src="scopehack.js"></script>
<script>
this.global.helloWorld = "helloWorld"; //"global scope"
this.helloWorld = "helloWorld" //"ModuleScope"
</script>

<iframe src="module.html"></iframe>

そして最後に「モジュール」module.html:

<script src="scopehack.js"></script>
<script>
    with( this.global ) { //poor mans RhinoJS scope injection, doesn't work for writing
        console.log( helloWorld ); //"global scope" - "helloWorld"
        console.log( this.helloWorld ); //"ModuleScope" undefined
    }
</script>

module.htmlとmain.htmlの両方で実際のグローバルオブジェクトはどちらですか?まだthisです。

TLDR:

var obj = {
"String": String,
"Object": Object,
.....
};

objグローバルオブジェクトを作成しません。

于 2011-11-26T17:18:44.600 に答える
2

実装に依存しないバージョンは簡単ではありません

(function (global) {
    // javascript framework
})(
   this && this.global || // ringoJS
   typeof root !== "undefined" && root || // node.js
   typeof global !== "undefined" && global || // more node.js
   typeof GLOBAL !== "undefined" && GLOBAL || // more node.js
   typeof window !== "undefined" && window || // browsers
   this // either undefined or some global default?
);

すべての環境の機能検出でハードコーディングする必要があります。

于 2011-11-29T15:19:19.443 に答える
1

EsailijaとRaynosの回答を読んだ後、私のコードthis.global || thisがnode.jsのすべてのケースで機能するとは限らないことを理解しました。また、呼び出された変数globalがグローバルスコープにすでに存在する場合は、ブラウザで失敗する可能性もあります。

this.globalEsailijaは、それは実際にはオブジェクトではないと指摘しglobal、代わりにそれthisglobalRingoJSのオブジェクトであると述べました。そして私は彼の議論を理解していますが、私の目的のために私は必要this.globalとし、そうではありませんthis

Raynosは、すべてのCommonJS環境の機能検出をハードコーディングすることを提案しました。ただし、現在サポートしているのはRingoJSとnode.jsのみなので、テストする必要があるのはとだけglobalですwindow。したがって、私はに固執することにしましたthis.global || this

それでも、前に言ったthis.global || thisように、benvieのコメントから理解したように、node.jsのすべてのケースで機能するとは限りません。node.js REPLで、私は必要thisであり、ではないことに気づきましたthis.global。ただし、this.global || thisを表しthis.globalます。node.jsモジュールでは、必要であり、ではthis.globalありませんthis。ただし、なので表現thisthis.globalますundefined。したがって、この問題を解決するために、私は最終的に次のコードを使用することにしました。

(function (global) {
    // javascript framework
})(typeof global !== "undefined" && global || this);

このコードを使用している理由は、node.jsモジュールではがであるためthis.globalですundefined。したがって、global直接使用する必要があります。したがって、RingoJSとnode.jsの両方でオブジェクトtypeof global !== "undefined" && globalを取得するために使用します。globalまた、ブラウザthisのオブジェクト( )およびデフォルトのフォールバックとして使用します。globalwindow

注:globalフレームワークがREPL内で直接使用されるとは思わないため、node.jsREPLでオブジェクトを検索するためのロジックは提供していません。globalただし、 benvieが指摘したように、node.jsでオブジェクトを見つけることの複雑さを理解すれば、それを見つけるためのロジックを書くことはかなり簡単なはずです。私は知らないことを知っています。

于 2011-12-02T07:00:26.003 に答える