JavaScript: Self-service function returns a closure. What is this for?

While researching one JavaScript library, I found the following construction:

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

      

theMethod is called like this:

c.theMethod(paramValue);

      

What did the author want to say with this expression?

Why not use a declaration like this:

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

      

+6


source to share


4 answers


This is for encapsulation . m1 is hidden from other methods and from external access by places that the method can use. Javascript programmers usually don't care about encapsulation (but they should be in non-trivial scenarios) because you need to use locks that complicate the design of the classes and, when implemented poorly, can degrade performance. This is why you don't see this kind of structure often outside of libraries.

Also your second code snippet is not equivalent. Something equivalent:

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

      



But then m1 is not private here.

Also note that in this code snippet m1 is only visible to the return function, if Method was a member of the class, other methods of this class will not be able to see m1 (making it different from the "private" keyword in Java). Also depending on how you declared that method m1 will be the java equivalent of "static" (m1 is a function on the object's prototype, which is static, unless it's not static on the prototype).

+3


source


Declaring a variable outside of a function forces the function to use the same object every time.

Example (with an integer instead of an object, for simplicity):

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

      

The self-start function works as follows:

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

      

When the object c

is created, the self-starting function calls itself and is theMethod

now equal to the return value of this function. In this case, the return value is a different function.



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

      

The variable m1

is available to the function because it was in scope when the function was defined.

Now when you call c.theMethod()

, you are always executing the inner function that was returned from the self-invoking function, which itself was only executed once at the time of the object's declaration.

The self-starting function works the same as any function. Consider:

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

      

You don't expect to parseInt()

be executed every time you use a variable c.theMethod

. Replace with parseInt

an anonymous function as in the original and it is exactly the same.

+4


source


@ Johan is right. Here's a handy tutorial on how closures work. http://www.javascriptkit.com/javatutors/closures.shtml

+1


source


What did the author want to say with this expression?

So that the value is m1

reused for every call. In your non-closure alternative, it will create a new object SomeClass

on every call. It is either used simply to improve performance, or (and) to maintain general state in the object m1

.

+1


source







All Articles