0

我有以下代码:

(function(){
...
var n = n || {};
...
})(); 

这就是我想要的,设置 n 等于 {} 因为这是第一次遇到它并且将是未定义的。不幸的是,由于 this 在函数内部,n因此仅限于该函数的范围,我不能在其他脚本中使用它。

我只想将行更改为n = n || {},但出现错误: ReferenceError: n is not defined

将其更改n = {}为按预期工作;然而,这不是我想要的。n当我不使用var和按预期工作(作为用于获取 OR 语句右侧的虚假值)时,我不明白为什么' 的不确定性会导致错误。根据我对var关键字的理解,我希望它是两者或两者都不是。

为什么会这样var,这是怎么回事?

4

9 回答 9

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在别处定义,它将被设置为undefinedvar n;然后{}在函数中设置为。通过在函数之外进行整个声明和赋值,您将获得所需的内容。我假设(根据您的问题的标题)实际上是命名空间,而不是一些任意的全局变量。那会很淘气!;-)

更新:

哦,顺便说一句,更好的方法可能是显式引用全局对象:

(function (exports) {
    exports.n = exports.n || {};
}(this));

这可能会与 node.js 之类的东西和任何可能包装你的代码的东西(比如 a $(function() { }))一起玩得更好。

于 2012-09-24T19:15:24.337 回答
2

您已经遇到了未定义变量和具有未定义值的已定义变量之间的区别。

引用未定义的变量将导致异常 ( ReferenceError: n is not defined)

引用具有未定义值的已定义变量很好,并且将false在条件中强制转换。

为避免这种情况,您可以将n其作为对象的属性进行引用window,因为属性永远不能未定义,只能具有未定义的值。

(function(){
...
window.n = window.n || {};
...
})(); 
于 2012-09-24T19:09:55.723 回答
1

n尚未声明,因此检查是否n为 true-like 将不起作用。您可以显式检查以查看是否n已声明:

n = typeof n !== 'undefined' ? n : {};

但这不是很好看。要将某些东西放在全局范围内,请window.n在函数之外使用n或声明:n

var n;

(function(){
...
n = n || {};
...
})(); 
于 2012-09-24T19:09:52.437 回答
1

1)小的改变将有助于:

(function() {
    var n = window.n = window.n || {};
    // Code of your module...
    n.hello = function() {
        alert('Hello');
    };
})();

n.hello();

​演示

通过这种方式,您拥有n全局可见的和对n函数内部同一对象的本地引用。

2)我也建议你用下一种方式重新设计它。

使每个模块像:

var MyApplication = (function(app) {

    // Code of the module here...

    app.hello = function() {
        console.log('Hello!');
    };

    return app;
})(MyApplication || {});

MyApplication.hello();
于 2012-09-24T19:11:09.023 回答
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();
于 2012-09-24T19:23:04.507 回答
0

var创建局部变量而不使用它会污染全局命名空间。浏览器应该防止这种情况发生,因为大多数情况下您不想创建全局变量。

你可以做的是使用window对象:

window.n = window.n || {}

但这仅适用于浏览器环境。如果不是这种情况(例如,您使用的是服务器端 JavaScript),则以这种方式检索全局对象:

var global = (function getGlobal(){
    return (function(){
        return this;
    }).call(null);
}());

接着:

global.n = global.n || {};
于 2012-09-24T19:09:29.100 回答
0

使用严格模式,您需要显式使用全局命名空间,通常是window; 更改要使用的行window.n应该可以满足您的需求:

window.n = window.n || {};
于 2012-09-24T19:07:46.507 回答
0

您可以var n;在代码之前添加,您将拥有全局n. var很重要,因为它使n函数本地化。

于 2012-09-24T19:07:55.163 回答
0

在函数结束时执行:

window.n = n;

这会将 n 放在全局命名空间中,允许您在其他脚本中使用它。

于 2012-09-24T19:06:46.787 回答