Как получить глобальный объект в JavaScript?

Я хочу проверить script, если какой-либо другой модуль уже загружен.

if (ModuleName) {
    // extend this module
}

Но если ModuleName не существует, то throw s.

Если бы я знал, что такое Global Object, я мог бы это использовать.

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

Но так как я хочу, чтобы мой модуль работал с обоими браузерами и node, rhino и т.д., я не могу предположить window.

Как я понимаю, это не работает в ES 5 с "use strict";

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

Это также приведет к сбою с созданным исключением

var MyGLOBAL = window || GLOBAL

Так кажется, что я остался с

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

Ни один из этих случаев не пройдет JSLint.

Я что-то пропустил?

Ответ 1

Ну, вы можете использовать оператор typeof, и если идентификатор не существует ни в каком месте цепочки областей видимости, он не будет бросать ReferenceError, он просто вернет "undefined":

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

Помните также, что значение this в глобальном коде относится к глобальному объекту, что означает, что если ваш оператор if находится в глобальном контексте, вы можете просто проверить this.ModuleName.

О методе (function () { return this; }());, вы правы, в строгом режиме значение this будет просто undefined.

В строгом режиме есть два способа получить ссылку на объект Global, независимо от того, где вы находитесь:

  • Через конструктор Function:

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

Функции, созданные с помощью конструктора Function, не наследуют строгость вызывающего, они строгие, только если они начинают свое тело с директивой 'use strict', в противном случае они являются нестрогими.

Этот метод совместим с любой реализацией ES3.

  • Через косвенный вызов eval, например:

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

Вышеупомянутое будет работать, потому что в ES5 косвенные вызовы eval используют глобальную среду Ввод Eval Code, шаг 1.

Но имейте в виду, что последнее решение не будет работать над реализациями ES3, поскольку косвенный вызов eval на ES3 будет использовать переменную и лексическую среду вызывающего в качестве сред для самого кода eval.

И, наконец, вам может оказаться полезным определить, поддерживается ли строгий режим:

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

Ответ 2

Сумасшедшее однострочное решение:

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

.

.

.

Работы

  • в каждой среде (которую я тестировал)
  • в строгом режиме
  • и даже во вложенной области

Обновление 2014-сентябрь-23

Теперь это может произойти, если заголовки HTTP в последних браузерах явно запрещают eval.

Обходным решением было бы попробовать/уловить исходное решение, поскольку известно, что только браузеры запускают этот тип подмножества JavaScript.

var global;

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

`` `

Пример:

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

}());

Проверено:

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

Почему:

Короче: это какая-то странная причуда. См. Комментарии ниже (или выше)

В strict mode this никогда не является глобальным, но также и в strict mode eval работает в отдельном контексте, в котором this всегда является глобальным.

В нестрогом режиме this - текущий контекст. Если нет текущего контекста, он предполагает глобальный. Анонимная функция не имеет контекста и, следовательно, в нестрогом режиме предполагает глобальный.

Sub Rant:

Там глупая ошибка в JavaScript, что 99,9% времени просто путает людей, называемых "оператором запятой".

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

Ответ 3

Почему просто не просто использовать это в глобальной области как параметр для функции обертки следующим образом?

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

Ответ 4

Здесь вы идете:)

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

Это должно работать где угодно, например, из-за другого закрытия.

Изменить - просто прочитайте свой пост более внимательно и просмотрите часть о строгом режиме ES5. Может ли кто-нибудь пролить свет на это? Это был общепринятый способ получить глобальный объект до тех пор, пока я помню... Я надеюсь, что он не закончит работу.

Изменить 2 - ответ CMS содержит дополнительную информацию о режиме строгого режима ES5 this.

Ответ 5

Я думаю, что это довольно хорошо в носороге, node, браузере и jslint (без дополнительных обходных флагов) - это поможет? Я что-то пропустил?

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

Хотя я сам склонен использовать оконный объект, и если мне нужно безгласное тестирование, я могу использовать env.js(rhino) или Phantom (node).

Ответ 6

У меня была эта проблема раньше, я не доволен решением, но он работает и передает JSLint (предположим, что браузер | предположим node):

"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 var, вы можете сделать свою проверку, а в конце типа script

delete GLOBAL.GLOBAL;

Ответ 7

Это не передача jslint: var Fn = Function, global = Fn('return this')();

Попробуйте сами: http://www.jslint.com/

это будет: var Fn = Function, global = new Fn('return this')();

Но эффективно это те же самые вещи в соответствии с MDN:

Вызов конструктора Function как функции (без использования нового оператора) имеет тот же эффект, что и вызов его как конструктора.

Ответ 8

Вот что я использую:

"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';
        }
    }
}

Ответ 9

Это следующее решение работает в:

  • Chrome
  • Node.JS
  • Firefox
  • MSIE
  • Работники веб-сайтов

Код:

(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 для имени переменной, которую вы хотели бы