我有以下代码:
(function(){
...
var n = n || {};
...
})();
这就是我想要的,设置n等于{},因为这是它第一次遇到并且将是未定义的。不幸的是,由于这在函数内部,n
的范围仅限于函数,我无法在其他脚本中使用它。
我想将该行更改为n = n || {}
,但我收到错误:ReferenceError: n is not defined
将其更改为n = {}
按预期工作;然而,这不是我想要的。当我不使用n
并按预期工作时,我不明白var
未定义导致错误的原因(用于获得正确方面的假值)当我做的时候,OR声明)根据我对var
关键字的理解,我希望它既可以兼有,也可以不兼容。
为什么var
很重要,这里发生了什么?
答案 0 :(得分:3)
所以听起来你在创建全局变量时遇到了麻烦。
好。
在JavaScript中创建全局变量比应该更容易。
您的问题是n
未定义(duh)。您无法引用尚未定义的变量。但你可能会想,“与使用var
的版本有什么不同?”这是一个很好的问题。
JavaScript做了一个叫做“挂起”变量定义的东西。如果在函数中定义变量,则该定义将隐式重定位到函数的顶部。所以当你写道:
var n = n || {};
真正发生的事情更接近:
var n;
n = n || {};
然而,事情并非如此简单,因为如果您尝试编写该代码,最终会将n
设置为{}
。但一般的本质是存在的。变量声明在赋值之前发生。
如果删除var
,则会导致引用错误,因为无法再提升声明。因此,一个“正确的”(我使用该术语松散,因为创建一个全局变量永远不是“正确的”)做你想要的方法就是把你的var
放在你的函数包装器之外。像这样:
var n = n || {};
(function () {
//do stuff.
}());
不幸的是,你不能这样做:
var n;
(function () {
n = n || {};
}());
与我上面的例子有同样的“问题”。如果n
在其他位置定义,则undefined
将其设置为var n;
,然后在函数中设置为{}
。通过在函数外部完成整个声明和赋值,您可以获得所需的内容。我假设(基于你的问题的标题)实际上是命名空间而不是一些任意的全局变量。那会很顽皮! ; - )
<强>更新强>
哦,顺便说一下,更好的方法是明确引用全局对象:
(function (exports) {
exports.n = exports.n || {};
}(this));
对于像node.js这样的东西以及任何可能包含你的代码的东西(比如$(function() { })
),这可能会更好。
答案 1 :(得分:2)
您遇到了未定义变量与具有未定义值的已定义变量之间的区别。
引用未定义的变量将导致异常(ReferenceError: n is not defined
)
引用具有未定义值的已定义变量很好,并且会在条件中强制转换为false
。
为避免这种情况,您可以将n
作为window
对象的属性引用,因为属性永远不会被定义,只有未定义的值。
(function(){
...
window.n = window.n || {};
...
})();
答案 2 :(得分:1)
n
尚未宣布,因此检查n
是否为真,将无效。您可以明确检查是否已声明n
:
n = typeof n !== 'undefined' ? n : {};
但是看起来不是很好。要在全局范围内放置某些内容,请使用window.n
代替n
或在您的函数之外声明n
:
var n;
(function(){
...
n = n || {};
...
})();
答案 3 :(得分:1)
1)小改变会有所帮助:
(function() {
var n = window.n = window.n || {};
// Code of your module...
n.hello = function() {
alert('Hello');
};
})();
n.hello();
的 DEMO 强>
通过这种方式,您可以n
,全局可见,同一对象的本地参考n
在你的功能中。
2)我建议你以下一种方式重新设计它。
将每个模块设为:
var MyApplication = (function(app) {
// Code of the module here...
app.hello = function() {
console.log('Hello!');
};
return app;
})(MyApplication || {});
MyApplication.hello();
答案 4 :(得分:0)
在函数结束时执行:
window.n = n;
这会将n放在全局命名空间中,允许您在其他脚本中使用它。
答案 5 :(得分:0)
使用严格模式,您需要显式使用全局命名空间,通常为window
;更改使用window.n
的行可以获得您想要的内容:
window.n = window.n || {};
答案 6 :(得分:0)
您可以在代码之前添加var n;
,然后您将拥有全局n
。 var
很重要,因为它使n
成为函数的本地。
答案 7 :(得分:0)
var
创建局部变量而不使用它会污染全局命名空间。浏览器应该阻止这种情况,因为大多数情况下你不想创建一个全局变量。
您可以使用window
对象:
window.n = window.n || {}
但这只适用于浏览器环境。如果不是这种情况(例如,您正在使用服务器端JavaScript),那么以这种方式检索全局对象:
var global = (function getGlobal(){
return (function(){
return this;
}).call(null);
}());
然后:
global.n = global.n || {};
答案 8 :(得分:0)
1)在第一轮评估中,var n = n || {};
您正在创建变量:
var n = undefined;
2)在第二轮评估中,您有条件地设置值:
n = undefined || {};
3)没有var语句,你有一个var,它根本不存在,被引用
var myVar = non_existant_var; // error
如果var已经存在,比如说,在全局范围内,或者当前函数嵌套在其中的任何其他函数,它将使用它在链上的路上找到的n
。如果不存在,它将适合。
所以不是故意在你的代码中挖洞,试图让代码知道你试图访问哪个范围,为什么不直接访问它?
(function (name) {
window[name] = window[name] || {}; // returns undefined and not reference error
var ns = window[name];
ns.init = function () {};
// .............
/* Don't return the application to a var -- it already exists in the global scope */
}("BigLongApplicationName"));
BigLongApplicationName.init(); // === window.BigLongApplicationName.init();