Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Studying one JavaScript library I found following construction:

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

theMethod is called as follows:

c.theMethod(paramValue);

What did the author want to say with this declaration?

Why not to use such declaration:

theMethod: function (theParameter) {
    var m1 = new SomeClass();
    this.someMethod();
    m1.methodCall(this.someField1);
    this.someField2 = 'some value';
}
like image 876
Paul Avatar asked Jun 21 '13 12:06

Paul


People also ask

What is the purpose of closures in JavaScript?

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function.

What is self calling function in JavaScript?

Self-Invoking FunctionsA self-invoking expression is invoked (started) automatically, without being called. Function expressions will execute automatically if the expression is followed by (). You cannot self-invoke a function declaration.

What is a function closure expression?

Nested functions are closures that have a name and can capture values from their enclosing function. Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.

Is every function a closure in JavaScript?

But as explained above, in JavaScript, all functions are naturally closures (there is only one exception, to be covered in The "new Function" syntax). That is: they automatically remember where they were created using a hidden [[Environment]] property, and then their code can access outer variables.


3 Answers

Declaring the variable outside the function makes the function use the same object every time.

An example (with an integer instead of an object, for simplicity's sake):

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-invoking function works like this:

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

When the object c is created, the self-invoking function invokes itself and theMethod now equals the return value of that function. In this case the return value is another 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.

From now on when you call c.theMethod() you are always executing the inner function that was returned from the self-invoking function, which itself executed only once at the time the object was declared.

The self-invoking function works just like any function. Consider:

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

You don't expect parseInt() to execute every time you use the c.theMethod variable. Replace parseInt with an anonymous function as in the original and it's exactly the same thing.

like image 55
JJJ Avatar answered Sep 20 '22 08:09

JJJ


It's for encapsulation. m1 is hidden to other methods and from external access by places that might use theMethod. Javascript programmers usually don't care about encapsulation (but they should on non-trivial scripts) because you need to use closures which complicates design of classes and when implemented poorly can reduce performance. That is why you don't see this kind of structure often outside of libraries.

Also your second piece of code is not equivalent. Something equivalent would be:

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 really private here.

Also note that in that piece of code m1 is only visible to the function returned, if theMethod was a member of a class the other methods of that class would not be able to see m1 (making it different than the "private" keyword on Java). Also depending on how you declared theMethod m1 would be the java equivalent to "static" (m1 is a function on the prototype of an object it's static, if it's not on a prototype it's not static).

like image 44
Hoffmann Avatar answered Sep 20 '22 08:09

Hoffmann


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

like image 33
Paul Avatar answered Sep 22 '22 08:09

Paul