Как получить глобальный объект в 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
, не наследуют строгость вызывающего, они строгие, только если они начинают свое тело с директивой 'use strict'
, в противном случае они являются нестрогими.
Этот метод совместим с любой реализацией ES3.
Вышеупомянутое будет работать, потому что в 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 для имени переменной, которую вы хотели бы