Как получить глобальный объект в 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.
я что-нибудь пропустил?
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