7

研究一个 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';
}
4

4 回答 4

5

在函数外部声明变量会使函数每次都使用同一个对象。

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

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变量时都执行。替换parseInt为原始函数中的匿名函数,它完全一样。

于 2013-06-21T12:34:41.070 回答
3

是为了封装。m1 对其他方法和可能使用该方法的地方的外部访问是隐藏的。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 是对象原型上的函数,它是静态的,如果它不在原型上,则它不是静态的)。

于 2013-06-21T12:53:06.110 回答
1

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

于 2013-06-21T12:39:05.660 回答
1

作者想用这个宣言表达什么?

m1应该为每个调用重用该值。在您的无闭包替代方案中,它会SomeClass在每次调用时实例化一个新对象。它要么仅用于性能改进,要么(和)保持m1对象中的公共状态。

于 2013-06-21T12:40:09.010 回答