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';
}
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.
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.
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.
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.
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.
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).
@Juhana is right. Here's a handy tutorial on how closures work. http://www.javascriptkit.com/javatutors/closures.shtml
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With