86 votes

Comment faire pour obtenir l'objet global en JavaScript?

Je veux vérifier dans un script si un autre module est déjà chargé.

if (ModuleName) {
    // extend this module
}

Mais si ModuleName n'existe pas, qu' throws.

Si je savais ce que l' Global Object a été je pouvais l'utiliser.

if (window.ModuleName) {
    // extend this module
}

Mais depuis que je tiens mon module de travailler avec les deux navigateurs et node, rhino, etc., Je ne peux pas assumer window.

Si je comprends bien, cela ne fonctionne pas dans l'ES 5 avec "use strict";

var MyGLOBAL = (function () {return this;}()); // MyGlobal becomes null

Ce sera aussi l'échec avec la levée d'une exception

var MyGLOBAL = window || GLOBAL

Donc il semble que je suis à gauche avec

try {
    // Extend ModuleName
} 
catch(ignore) {
}

Aucun de ces cas va passer JSLint.

Ai-je raté quelque chose?

102voto

CMS Points 315406

Eh bien, vous pouvez utiliser l' typeof de l'opérateur, et si l'identifiant n'existe pas dans n'importe quel endroit de la chaîne d'étendue, il ne sera pas jeter un ReferenceError, il sera de retour "undefined":

if (typeof ModuleName != 'undefined') {
  //...
}

Rappelez-vous aussi que l' this de la valeur sur le code Mondial, se réfère à l'objet global, ce qui signifie que si votre if déclaration est le contexte mondial, vous pouvez simplement cocher this.ModuleName.

À propos de l' (function () { return this; }()); technique, vous avez raison, sur le mode strict de l' this de la valeur sera simplement undefined.

En vertu de la mode strict, il y a deux façons d'obtenir une référence à l'objet Global, peu importe où vous êtes:

  • Par le biais de l' Function constructeur de:

    var global = Function('return this')();
    

Fonctions créées avec l' Function constructeur de ne pas hériter de la rigueur de l'appelant, ils sont stricts que si ils commencent leur corps avec l' 'use strict' directive, sinon ils sont non-strictes.

Cette méthode est compatible avec n'importe quel ES3 mise en œuvre.

  • Par le biais d'un indirectes eval appel, par exemple:

    "use strict";
    var get = eval;
    var global = get("this");
    

Le ci-dessus ne fonctionne, parce que dans l'ES5, indirects appels d' eval, l'utilisation de l' environnement mondial est la variable de l'environnement et de l'environnement lexical pour l'eval code.

Voir les détails sur la Saisie Eval Code, à l'Étape 1.

Mais sachez que la dernière solution ne fonctionnera pas sur ES3 implémentations, car un appel indirect à l' eval sur ES3 utilisera les variables lexicales et des environnements de l'appelant que les environnements pour les eval code lui-même.

Et enfin, vous pourriez trouver utile de détecter si le mode strict est pris en charge:

var isStrictSupported = (function () { "use strict"; return !this; })();

27voto

CoolAJ86 Points 19341

Fou une solution en ligne:

var global = Function('return this')() || (42, eval)('this');

.

.

.

Fonctionne

  • dans chaque environnement (que j'ai testé)
  • en mode strict
  • et même dans une étude portée

Mise À Jour 2014-Sept-23

Cela peut échouer si les en-têtes HTTP dans les navigateurs les plus récents interdisent explicitement eval.

Une solution de contournement serait de try / catch de la solution originale que seuls les navigateurs sont connus pour exécuter ce type de sous-ensemble de JavaScript.

var global;

try {
  global = Function('return this')() || (42, eval)('this');
} catch(e) {
  global = window;
}

``

Exemple:

(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');

}());

Testé:

  • Chrome v12
  • Node.JS v0.4.9
  • Firefox v5
  • MSIE 8

Pourquoi:

En bref: c'est un peu bizarre caprice. Voir les commentaires ci-dessous (ou le post ci-dessus)

En strict mode this n'est jamais le global, mais aussi dans strict mode eval fonctionne dans un autre contexte dans lequel this est toujours le mondial.

Non le mode strict this est le contexte actuel. Si il n'y a pas de contexte, il assume le mondial. Une fonction anonyme n'a pas de contexte et donc de la non-mode strict suppose le mondial.

Sous Coup De Gueule:

Il y a un idiot misfeature de JavaScript que 99,9% du temps confond tout simplement les gens ont appelé la " virgule de l'opérateur.

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

4voto

Pourquoi ne pas simplement utiliser ce dans une portée mondiale comme paramètre à une fonction wrapper, comme suit?

(function (global) {
    'use strict';
    // Code
}(this));

3voto

Dagg Nabbit Points 23918

Ici, vous allez :)

var globalObject = (function(){return this;})();

Cela devrait fonctionner à partir de n'importe où, par exemple à partir d'une autre fermeture.

Edit viens de lire votre message avec plus de soin et vu la partie sur ES5 mode strict. Quelqu'un peut-il faire la lumière sur qui? Cela a été le moyen de l'objet global pour aussi longtemps que je me souvienne... j'espère qu'on ne va pas se briser.

Edit 2 - CMS réponse a plus d'info sur l'ES5 mode strict du traitement de l' this.

2voto

Szabolcs Kurdi Points 204

Je pense que c'est à peu près d'accord dans rhino, un nœud, un navigateur et avec jslint (sans autre solution de contournement des drapeaux) - serait-ce de l'aide? Ai-je raté quelque chose?

x = 1;
(function(global){
    "use strict";
    console.log(global.x);
}(this));

Bien que j'ai moi-même tendance à utiliser la fenêtre de l'objet et si j'ai besoin d'headless tests que je peux utiliser env.js (rhino) ou un Fantôme (nœud).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X