JavaScript:自调用函数返回一个闭包。它是为了什么?

时间:2013-06-21 12:29:06

标签: javascript closures

研究我发现的一个JavaScript库:

theMethod: function () {
    var m1 = new SomeClass();
    return function (theParameter) {
        this.someMethod();
        m1.methodCall(this.someField1);
        this.someField2 = 'some value';
    }
}()

theMethod的调用如下:

c.theMethod(paramValue);

作者想用这个宣言说什么?

为什么不使用这样的声明:

theMethod: function (theParameter) {
    var m1 = new SomeClass();
    this.someMethod();
    m1.methodCall(this.someField1);
    this.someField2 = 'some value';
}

4 个答案:

答案 0 :(得分:4)

在函数外声明变量使得函数每次都使用相同的对象。

一个例子(为了简单起见,用整数而不是对象):

var c = { 
    theMethod: function () {
        var m1 = 0;
        return function (theParameter) {
            m1++;
            console.log( m1 );
        }
    }()
};

c.theMethod(); c.theMethod();  // output: 1 2


var d = { 
    theMethod: function () {
        return function (theParameter) {
            var m1 = 0;
            m1++;
            console.log( m1 );
        }
    }()
};

d.theMethod(); d.theMethod();  // output: 1 1

自调函数的工作原理如下:

var c = { 
    theMethod: function () {
        var m1 = 0;
        return function (theParameter) {
            m1++;
            console.log( m1 );
        }
    }()
};

当创建对象c时,自调用函数会调用自身,theMethod现在等于该函数的返回值。在这种情况下,返回值是另一个函数。

c.theMethod = function( theParameter ) {
    m1++;
    console.log( m1 );
};

变量m1可用于函数,因为它在定义函数时在范围内。

从现在开始,当你调用c.theMethod()时,你总是执行从自调用函数返回的内部函数,该函数在声明对象时只执行一次。

自调用函数就像任何函数一样工作。考虑:

var c = { 
    theMethod: parseInt( someVariable, 10 )
};

每次使用parseInt()变量时,都不希望c.theMethod执行。将<{1}}替换为原始的匿名函数,它完全相同。

答案 1 :(得分:3)

适用于encapsulation。 m1对于其他方法以及可能使用theMethod的地方的外部访问是隐藏的。 Javascript程序员通常不关心封装(但它们应该放在非平凡的脚本上),因为你需要使用使类设计复杂化的闭包,如果实现不好会降低性能。这就是为什么你不经常在图书馆之外看到这种结构。

此外,您的第二段代码也不相同。等价的东西是:

theMethod: function (theParameter) {
    if (typeof this.prototype.__private__ === "undefined") {
        this.prototype.__private__= {}
    }
    if (typeof this.__private__.m1 === "undefined") {
        this.prototype.__private__.m1= new SomeClass();
    }
    this.someMethod();
    this.__private__.m1.methodCall(this.someField1);
    this.someField2 = 'some value';
}

但是m1在这里并不是非常私密。

另请注意,在该段代码中,m1仅对返回的函数可见,如果theMethod是类的成员,则该类的其他方法将无法看到m1(使其与“private”不同) Java上的关键字)。同样取决于你如何声明theMethod m1将是等效于“静态”的java(m1是对象原型上的一个函数,它是静态的,如果它不在原型上则不是静态的)。

答案 2 :(得分:1)

@Juhana是对的。这是一个关于闭包如何工作的方便教程。 http://www.javascriptkit.com/javatutors/closures.shtml

答案 3 :(得分:1)

  

作者想用这个宣言说什么?

每次调用都应该重用m1值。在无关闭的替代方案中,它会在每次调用时实例化一个新的SomeClass对象。它或者仅用于提高性能,或者(和)在m1对象中维护一个公共状态。