特定の他のモジュールが既にロードされている場合、スクリプトをチェックインしたいです。
if (ModuleName) {
// extend this module
}
ただし、ModuleName
が存在しない場合は、そのthrow
sです。
Global Object
が何であるかを知っていれば、それを使用できます。
if (window.ModuleName) {
// extend this module
}
しかし、ブラウザとnode
、rhino
などの両方でモジュールを動作させたいので、window
と仮定することはできません。
私が理解しているように、これは"use strict"
を使用するES 5では機能しません。
var MyGLOBAL = (function () {return this;}()); // MyGlobal becomes null
これもスローされた例外で失敗します
var MyGLOBAL = window || GLOBAL
だから私は残っているようだ
try {
// Extend ModuleName
}
catch(ignore) {
}
これらのケースはいずれもJSLintに合格しません。
私は何かが欠けていますか?
さて、typeof
演算子を使用できます。識別子がスコープチェーンのどの場所にも存在しない場合、notReferenceError
をスローすると、"undefined"
が返されます。
if (typeof ModuleName != 'undefined') {
//...
}
また、グローバルコードのthis
値はグローバルオブジェクトを参照することを忘れないでください。つまり、if
ステートメントがグローバルコンテキスト上にある場合は、this.ModuleName
を確認するだけです。
(function () { return this; }());
テクニックについて、あなたは正しいです。厳格モードでは、this
値はundefined
になります。
厳密モードでは、どこにいてもグローバルオブジェクトへの参照を取得する方法が2つあります。
Function
コンストラクターを介して:
var global = Function('return this')();
Function
コンストラクターで作成された関数は、呼び出し元の厳密性を継承しません。'use strict'
ディレクティブで本体を開始する場合のみ厳密であり、そうでない場合は厳密ではありません。
この方法は、あらゆるES3実装と互換性があります。
indirect eval
callを介して、たとえば:
"use strict";
var get = eval;
var global = get("this");
ES5では、eval
の間接呼び出しで、 グローバル環境 をevalコードの変数環境とレキシカル環境の両方として使用するため、上記が機能します。
評価コードの入力 、ステップ1の詳細を参照してください。
ただし、ES3でeval
を間接的に呼び出すと、呼び出し元の変数およびレキシカルな環境がevalコード自体の環境として使用されるため、最後のソリューションはES3実装では機能しないことに注意してください。
そして最後に、厳密モードがサポートされているかどうかを検出するのに役立つことがあります。
var isStrictSupported = (function () { "use strict"; return !this; })();
今日のすべてのWebpackとBroccolis、GulpsとGrunts、TypeScriptsとAltScripts、およびcreate-react-appsなどを使用すると、これはまったく役に立ちませんが、単純で古いVanillaJSで作業していて、同形、これはおそらくあなたの最良の選択肢です:
var global
try {
global = Function('return this')();
} catch(e) {
global = window;
}
Functionコンストラクターは常にグローバルな非厳密スコープで実行されるため、ノードで--use_strict
を使用している場合でも、Functionコンストラクターの呼び出しは機能します。
Functionコンストラクターが失敗するのは、CSPヘッダーによってeval
が無効になっているブラウザーを使用しているためです。
もちろん、Denoが途中(ノード置換)である場合、Functionコンストラクタも許可されない場合があります。この場合、global
、module
、exports
、globalThis
、およびwindow
などのオブジェクトの列挙に戻り、グローバルに徹底的に...:-/
var global = Function('return this')() || (42, eval)('this');
。
。
。
最新のブラウザのHTTPヘッダーが明示的にevalを禁止している場合、これは失敗する可能性があります。
回避策は、このタイプのJavaScriptのサブセットを実行するのはブラウザーのみであるため、元のソリューションを試す/キャッチすることです。
var global;
try {
global = Function('return this')() || (42, eval)('this');
} catch(e) {
global = window;
}
Example:
---
(function () {
var global = Function('return this')() || (42, eval)('this');
console.log(global);
// es3 context is `global`, es5 is `null`
(function () {
"use strict";
var global = Function('return this')() || (42, eval)('this');
console.log(global);
}());
// es3 and es5 context is 'someNewContext'
(function () {
var global = Function('return this')() || (42, eval)('this');
console.log(global);
}).call('someNewContext');
}());
Tested:
---
* Chrome v12
* Node.JS v0.4.9
* Firefox v5
* MSIE 8
Why:
---
In short: it's some weird quirk. See the comments below (or the post above)
In `strict mode` `this` is never the global, but also in `strict mode` `eval` operates in a separate context in which `this` *is* always the global.
In non-strict mode `this` is the current context. If there is no current context, it assumes the global. An anonymous function has no context and hence in non-strict mode assumes the global.
Sub Rant:
There's a silly misfeature of JavaScript that 99.9% of the time just confuses people called the 'comma operator'.
var a = 0, b = 1;
a = 0, 1; // 1
(a = 0), 1; // 1
a = (0, 1); // 1
a = (42, eval); // eval
a('this'); // the global object
次のように、単にラッパー関数のパラメーターとしてグローバルスコープでこれを使用しないでください。
(function (global) {
'use strict';
// Code
}(this));
これは、rhino、node、browser、およびjslint(追加の回避策フラグなし)では大丈夫だと思います-これは役立ちますか?何か不足していますか?
x = 1;
(function(global){
"use strict";
console.log(global.x);
}(this));
私自身はウィンドウオブジェクトを使用する傾向がありますが、ヘッドレステストが必要な場合は、env.js(rhino)またはPhantom(ノード)を使用できます。
どうぞ :)
var globalObject = (function(){return this;})();
これはどこからでも、たとえば別のクロージャー内から機能するはずです。
編集-投稿をより注意深く読んで、ES5 strictモードに関する部分を見ただけです。誰かがそれについてもう少し光を当てることができますか?これは、覚えている限り、グローバルオブジェクトを取得する方法として受け入れられてきました。
編集2-CMSの答えには、this
のES5 strictモードの扱いに関する詳細があります。
ECMAScriptはすぐにこれを標準に追加します: https://github.com/tc39/proposal-global
完了するまで、これが推奨されます。
var getGlobal = function () {
// the only reliable means to get the global object is
// `Function('return this')()`
// However, this causes CSP violations in Chrome apps.
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};
これはjslintを渡していません:var Fn = Function, global = Fn('return this')();
自分で試してみてください: http://www.jslint.com/
これは:var Fn = Function, global = new Fn('return this')();
しかし、事実上、これらは [〜#〜] mdn [〜#〜] に従って同じものです。
Functionコンストラクターを(new演算子を使用せずに)関数として呼び出すと、コンストラクターとして呼び出すのと同じ効果があります。
以前にこの問題がありましたが、解決策に満足していませんが、動作し、JSLintを渡します(ブラウザーを想定|ノードを想定):
"use strict";
var GLOBAL;
try{
/*BROWSER*/
GLOBAL = window;
}catch(e){
/*NODE*/
GLOBAL = global;
}
if(GLOBAL.GLOBAL !== GLOBAL){
throw new Error("library cannot find the global object");
}
gLOBAL変数を取得したら、チェックを実行し、スクリプトタイプの最後に
delete GLOBAL.GLOBAL;
次のソリューションは以下で機能します。
コードは次のとおりです。
(function (__global) {
// __global here points to the global object
})(typeof window !== "undefined" ? window :
typeof WorkerGlobalScope !== "undefined" ? self :
typeof global !== "undefined" ? global :
Function("return this;")());
必要な変数の名前のXを変更するだけです
私が使用しているものは次のとおりです。
"use strict";
if(this && this.hasOwnProperty && !this.hasOwnProperty('globalScope')){
try {
globalScope = Function('return this')();
}catch(ex){
if(this.hasOwnProperty('window')){
globalScope = window;
}else{
throw 'globalScope not found';
}
}
}