Как получить глобальный объект в JavaScript?
я хочу проверить скрипт, если уже загружен определенный другой модуль.
if (ModuleName) {
// extend this module
}
но если ModuleName
не существует, что throw
s.
если бы я знал, что такое Global Object
я мог бы использовать это.
if (window.ModuleName) {
// extend this module
}
но так как я хочу, чтобы мой модуль для работы с браузерами и node
, rhino
, etc. Я не могу предположить window
.
как я понимаю, это не работает в ES 5 с "use strict"
;
var MyGLOBAL = (function () {return this;}()); // MyGlobal becomes null
это будет не исключение
var MyGLOBAL = window || GLOBAL
похоже, я остался с
try {
// Extend ModuleName
}
catch(ignore) {
}
ни один из этих случаев не пройдет JSLint.
я что-нибудь пропустил?
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 в последних браузерах явно запрещают 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');
}());
проверил:
- хром V12 объемом
- узел.С JS версии v0.4.9
- в Firefox У5
- MSIE 8
почему:
короче говоря: это какая-то странная причуда. См. комментарии ниже (или сообщение выше)
на strict mode
this
никогда не глобальный, но также в strict mode
eval
работает в отдельном контексте, в котором this
is всегда глобальные.
в нестрогом режиме 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';
}
}
}
Это решение работает в:
- Chrome
- узел.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 для имени переменной, которую вы хотели бы