自调用函数返回闭包.这是干什么用的?

JavaScript: self-calling function returns a closure. What is it for?

本文关键字:干什么 调用 函数 返回 闭包      更新时间:2023-09-26

研究一个JavaScript库,我发现以下结构:

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

方法被调用如下:

c.theMethod(paramValue);

作者想用这个声明表达什么?

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

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

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

示例(为简单起见,使用整数代替对象):

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 )
};

不要期望每次使用c.theMethod变量时都执行parseInt()。将parseInt替换为原始的匿名函数,结果完全相同。

用于封装。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(这与Java中的"private"关键字不同)。也取决于你如何声明的方法m1将是java等效的"静态"(m1是一个函数在一个对象的原型,它是静态的,如果它不是在一个原型,它不是静态的)。

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

作者想用这个声明表达什么?

每次调用都应该重用m1值。在无闭包的替代方案中,它将在每次调用时实例化一个新的SomeClass对象。它可以简单地用于性能改进,或者(和)维护m1对象中的公共状态。