用于作用域关闭的Javascript自调用匿名函数

用于作用域关闭的Javascript自调用匿名函数,javascript,Javascript,可能重复: 在我一直使用的库中,我越来越多地看到这样的代码: (function (window) { var Foo = function () { } window.Foo = Foo; })(window); 我看到这样做的理由是在创建(伪)类时避免在全局范围内工作。但是,如果我错了,请纠正我,我始终理解窗口是全局范围。我相信,当你创建一个全局变量时,你实际上只是在向窗口添加一个属性而已。。。除非这是ES5标准的变化 那么,基本上,重点是什么?这样组织代码的唯

可能重复:

在我一直使用的库中,我越来越多地看到这样的代码:

(function (window) {
    var Foo = function () {
    }

    window.Foo = Foo;
})(window);
我看到这样做的理由是在创建(伪)类时避免在全局范围内工作。但是,如果我错了,请纠正我,我始终理解窗口是全局范围。我相信,当你创建一个全局变量时,你实际上只是在向窗口添加一个属性而已。。。除非这是ES5标准的变化

那么,基本上,重点是什么?这样组织代码的唯一好处是,如果您希望在以后通过传入除window之外的参数来轻松更改类的名称空间。

事实上,如果您忘记对任何变量声明使用
var
,strict mode会引发异常。但是,即使不使用外部闭合,这种方法也可以工作

使用此模式更能保护自己免受外部javascript世界的影响。例如,某些其他脚本覆盖window.undefined或任何其他变量,您可以获取该闭包中的值,以便从中保存访问它

比如说

(function _myApp( win, doc, undef ) {
    // app code
}( this, this.document ));
此外,当使用var声明变量或创建函数声明时,这些变量总是分别存储在当前激活对象和词法环境记录中。这意味着,在不使用函数上下文的情况下,您可以轻松地从其他点覆盖方法和变量,因为所有这些都将存储在当前上下文中(即全局上下文)

因此:


这是因为闭包和上下文,但是如果您使用相同的代码,而不使用函数上下文,我们显然会覆盖我们的
myVar
myFunc
。这可能发生在任何地方,在同一个文件中或在另一个加载的脚本中。

与全局变量一样,您至少需要一个变量,否则无法访问脚本。您提供的代码是创建一个全局变量的一种方法。我喜欢这样:

window.Foo = (function () {
    var func = function () {
        //  ...
    };

    return {
        func: func
    };
})();

您的回答是对的,但不同之处在于函数内部的代码起着自动
init
函数的作用

(function (window) {
    var Foo = function () {
    }

    var Bar = 69; // not in global scope

    window.Foo = Foo; // in global scope
})(window);
相对于

var Foo = function () { // in global scope
}

var Bar = 69; // in global scope


检查此线程:以及此线程:。。。看起来这主要是出于性能原因,与函数查找速度有关。答案是,在该函数范围内定义各种变量时,只有Foo成员附加到最后的窗口。所以,您可以让您的逻辑变量执行其业务,并保持在全球范围之外;DR:window现在可以被覆盖,同时边际性能和小型化也会带来好处。仍然不需要将window作为参数传入。通过返回要指定的对象的IIFE,可以实现相同的效果。参见jbabey的答案。这是使用自调用匿名函数的好处,但与作用域问题无关,这是Douglas Crockford的方法,从这里开始:我倾向于编写js的方式,我只会为我的类创建全局变量。因此,拥有额外的作用域函数似乎是不必要的。小型化和性能优势非常有趣though@blask额外的作用域是实现公共和私有方法的唯一途径,这是没有必要的。这个特殊的模式叫做yes,我也使用了一个额外的闭包,很抱歉,我特别指的是以原始postYes的方式传递窗口对象,我很高兴看到这个异常。但是,以这种方式从一个没有外部闭包的var声明一个全局变量似乎并没有什么范围上的好处。安全方面的好处很有趣,性能和缩小方面也有一些改进。@blask:有趣的是,我不久前专门对
窗口
对象的访问进行了基准测试,因此,访问缓存引用总是比直接访问
窗口
更快。仅依靠浏览器作用域链查找将获得最差的性能,例如,仅调用
setTimeout
var Foo = function () { // in global scope
}

var Bar = 69; // in global scope
var Foo = function () { // in global scope
}

function init () {
    var Bar = 69; // not in global scope
}
init();