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



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



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.



я что-нибудь пропустил?

449   10  

10 ответов:

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

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

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

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

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

  • до Function конструктора:

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

функции, созданные с помощью Function конструктор не наследует строгость вызывающего, они строги только в том случае, если они начинают свое тело с

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

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

.

.

.

работает

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

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

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

обходным путем было бы попробовать / поймать оригинал решение, поскольку только браузеры, как известно, запускают этот тип подмножества 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
  • узел.JS v0.4. 9
  • Firefox v5
  • MSIE 8

почему:

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

на strict modethis никогда не глобальный, но также в strict modeeval работает в отдельном контексте, в котором 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

почему бы просто не использовать это в глобальной области как param для функции-оболочки, как показано ниже?

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

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

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

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

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

Edit 2-CMS' ответ имеет больше информации о лечении строгого режима ES5 this.

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

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

хотя я сам склонен использовать объект window, и если мне нужно безголовое тестирование, я могу использовать env.js (носорог) или фантом (узел).

у меня была эта проблема раньше, я не доволен решением, но он работает и передает 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");
}

после того, как у вас есть глобальный var вы можете сделать свою проверку, и в конце скрипта типа

delete GLOBAL.GLOBAL;

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

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

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

но фактически это одно и то же в соответствии с MDN:

вызов конструктора function как функции (без использования оператора new) имеет тот же самый эффект как вызов его конструктора.

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

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

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

Это решение работает в:

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

Comments

    Ничего не найдено.