Ich möchte in einem Skript einchecken, ob ein bestimmtes anderes Modul bereits geladen ist.
if (ModuleName) {
// extend this module
}
Aber wenn ModuleName
es nicht existiert, ist das throw
s.
Wenn ich wüsste, was das ist, Global Object
könnte ich das gebrauchen.
if (window.ModuleName) {
// extend this module
}
Aber da ich mein Modul zur Arbeit mit beiden Browsern will und node
, rhino
etc., kann ich nicht annehmen window
.
Soweit ich weiß, funktioniert dies in ES 5 mit nicht "use strict"
.
var MyGLOBAL = (function () {return this;}()); // MyGlobal becomes null
Dies schlägt auch mit einer ausgelösten Ausnahme fehl
var MyGLOBAL = window || GLOBAL
Es scheint also, als wäre ich übrig geblieben
try {
// Extend ModuleName
}
catch(ignore) {
}
Keiner dieser Fälle besteht JSLint.
Vermisse ich etwas
javascript
global
coolaj86
quelle
quelle
Fn
Variable:var global = (function (fn) { return fn('return this'); }(Function));
()
.var global = (function(){return this}).apply(null)
. Weitere Infos unter developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Antworten:
Nun, Sie können den
typeof
Operator verwenden, und wenn der Bezeichner an keiner Stelle der Gültigkeitsbereichskette vorhanden ist, wird kein a ausgelöstReferenceError
, sondern nur Folgendes zurückgegeben"undefined"
:if (typeof ModuleName != 'undefined') { //... }
Denken Sie auch daran, dass sich der
this
Wert für globalen Code auf das globale Objekt bezieht. Wenn sich Ihreif
Anweisung im globalen Kontext befindet, können Sie dies einfach überprüfenthis.ModuleName
.In Bezug auf die
(function () { return this; }());
Technik haben Sie Recht, im strengen Modus wird derthis
Wert einfach seinundefined
.Im strengen Modus gibt es zwei Möglichkeiten, einen Verweis auf das globale Objekt abzurufen, unabhängig davon, wo Sie sich befinden:
Durch den
Function
Konstruktor:var global = Function('return this')();
Mit dem
Function
Konstruktor erstellte Funktionen erben nicht die Strenge des Aufrufers, sie sind nur dann streng, wenn sie ihren Body mit der'use strict'
Direktive beginnen, andernfalls sind sie nicht streng.Diese Methode ist mit jeder ES3-Implementierung kompatibel.
Durch einen indirekten
eval
Anruf zum Beispiel:"use strict"; var get = eval; var global = get("this");
Dies funktioniert, da in ES5 bei indirekten Aufrufen
eval
die globale Umgebung sowohl als variable Umgebung als auch als lexikalische Umgebung für den Bewertungscode verwendet wird.Siehe Details zur Eingabe des Eval-Codes , Schritt 1.
Beachten Sie jedoch, dass die letzte Lösung bei ES3-Implementierungen nicht funktioniert, da bei einem indirekten Aufruf
eval
von ES3 die variablen und lexikalischen Umgebungen des Aufrufers als Umgebungen für den Evaluierungscode selbst verwendet werden.Und schließlich können Sie nützlich sein, um festzustellen, ob der strikte Modus unterstützt wird:
var isStrictSupported = (function () { "use strict"; return !this; })();
quelle
Function
in einem untergeordneten Bereich überschrieben oder sogar beschattet werden kann. Es ist besser zu verwendenvar global = (() => {}).constructor('return this')();
Update 2019
Mit all den heutigen Webpacks und Broccolis, Gulps und Grunts, TypeScripts und AltScripts sowie Create-React-Apps usw. ist dies ziemlich nutzlos, aber wenn Sie nur mit einfachem, altem VanillaJS arbeiten und machen möchten es ist isomorph, dies ist wahrscheinlich Ihre beste Option:
var global try { global = Function('return this')(); } catch(e) { global = window; }
Der Funktionskonstruktoraufruf funktioniert auch bei Verwendung
--use_strict
im Knoten, da der Funktionskonstruktor immer in einem globalen, nicht strengen Bereich ausgeführt wird.Wenn der Funktionskonstruktor fehlschlägt, liegt dies daran, dass Sie sich in einem Browser befinden, dessen
eval
CSP-Header deaktiviert sind.Natürlich mit Deno auf dem Weg (der Knoten Ersatz), können sie auch die Funktion Konstruktor nicht zulassen, wobei in diesem Fall ist es an der Rückseite Aufzählen Objekte wie
global
,module
,exports
,globalThis
undwindow
, und dann die Ente-Typprüfung abschließend die globalen ist ... : - /Verrückte einzeilige Lösung (Original):
var global = Function('return this')() || (42, eval)('this');
.
.
.
Funktioniert
Update 2014-Sept-23
Dies kann jetzt fehlschlagen, wenn HTTP-Header in den neuesten Browsern die Auswertung ausdrücklich verbieten.
Eine Problemumgehung wäre, die ursprüngliche Lösung zu versuchen / zu fangen, da nur Browser bekannt sind, die diese Art von Teilmenge von JavaScript ausführen.
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
quelle
eval
. In ES5 ist ein Aufruf von nur danneval
direkt , wenn derCallExpression
von a gebildet wirdMemberExpression
, der zwei Bedingungen erfüllt: 1. Der Basiswert der Referenz ist ein Umgebungsdatensatz. 2. Der Referenzname lautet"eval"
: Jede andere Art deseval
Aufrufs führt zu einem indirekten Aufruf. Seien Sie vorsichtig, da dieses Verhalten in ES3 nicht funktioniert, da das Konzept der direkten Aufrufe von eval nicht existierte. Versuchen Sie dieses Beispiel mit einer ES3-Implementierung (z. B. IE8)eval
Teil überhaupt nicht erforderlich ist. Sie benötigen lediglich,var global = Function('return this')();
wie ich beschrieben habe, "Funktionen, die mit demFunction
Konstruktor don erstellt wurden 'erbe nicht die Strenge des Aufrufers ", was bedeutet, dass der Rückgabewert dieser Funktion immer das globale Objekt ist, unabhängig von der Implementierung-. Dereval
Aufruf auf der rechten Seite des||
Operators wird niemals erfolgen, da die Funktion immer einen wahrheitsgemäßen Wert liefert (das globale Objekt).a = 0, 1; // 0
und(a = 0), 1; // 0
beide Ausdrücke zurückkehren1
. Vielleicht// a = 0
wäre es besser.(42, eval)('this')
ausgewertet? Mit anderen Worten, wann wirdFunction('return this')()
es falsch sein?Warum verwenden Sie dies nicht einfach wie folgt in einem globalen Bereich als Parameter für eine Wrapper-Funktion?
(function (global) { 'use strict'; // Code }(this));
quelle
this === module.exports
.Bitte schön :)
var globalObject = (function(){return this;})();
Dies sollte von überall aus funktionieren, beispielsweise von einem anderen Verschluss aus.
Bearbeiten - lesen Sie einfach Ihren Beitrag genauer durch und sehen Sie den Teil über den strengen ES5-Modus. Kann jemand mehr Licht ins Dunkel bringen? Dies war der akzeptierte Weg, um das globale Objekt zu erhalten, solange ich mich erinnern kann ... Ich hoffe, dass es nicht kaputt geht.
Bearbeiten 2 - Die Antwort von CMS enthält weitere Informationen zur Behandlung von ES5 im strengen Modus
this
.quelle
Ich denke, das ist in Nashorn, Knoten, Browser und mit jslint (ohne zusätzliche Workaround-Flags) ziemlich in Ordnung - würde dies helfen? Vermisse ich etwas
x = 1; (function(global){ "use strict"; console.log(global.x); }(this));
Obwohl ich selbst dazu neige, das Fensterobjekt zu verwenden, und wenn ich kopflose Tests benötige, kann ich env.js (Nashorn) oder Phantom (Knoten) verwenden.
quelle
this
möglicherweise nicht auf das globale Objekt verwiesen wird.ECMAScript wird dies in Kürze zu seinem Standard hinzufügen: https://github.com/tc39/proposal-global
Bis es fertig ist, wird Folgendes empfohlen:
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'); };
quelle
Dies geht nicht an jslint vorbei:
var Fn = Function, global = Fn('return this')();
Probieren Sie es selbst aus: http://www.jslint.com/
dieser Wille:
var Fn = Function, global = new Fn('return this')();
Aber effektiv sind das laut MDN dasselbe :
quelle
Diese folgende Lösung funktioniert in:
Der Code lautet:
(function (__global) { // __global here points to the global object })(typeof window !== "undefined" ? window : typeof WorkerGlobalScope !== "undefined" ? self : typeof global !== "undefined" ? global : Function("return this;")());
Sie müssen nur X für den Namen der Variablen ändern, die Sie möchten
quelle
Ich hatte dieses Problem schon einmal, ich bin mit der Lösung nicht zufrieden, aber es funktioniert und übergibt JSLint (Browser annehmen | Knoten annehmen):
"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"); }
Sobald Sie die GLOBAL-Variable haben, können Sie Ihre Überprüfung durchführen und am Ende des Skripttyps
delete GLOBAL.GLOBAL;
quelle
Folgendes verwende ich:
"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'; } } }
quelle