It took me days to really understand what a closure is in javascript, and finally I have grokked the core concept. And here are some share to whom is new to the language like me. And this article is for some basic concepts about javascript functions, which is very important when learning the closure.
It is a little hard to get the concept by the definition. I have been reading articles and books these days to understand how javascript function works, which seems so different from other languages like C, Python, etc. The more you get, the more confused you are, as people have really different understandings. Some of them are confusing, and some of them are misunderstanding or even wrong, as everyone makes mistakes. And finally I come to the idea that the best way to learn it is typing the code to you browser and debug to see how it works. It really helps alot. Let me explore it a little bit deeper by the examples.
We first started by some basic concept about javascript function:
Definition
There are 3 ways to define a function in javascript:
- function funcname(para1, para2){ … }
- var funcname = function(para1, para2){ … }
- var funcname = Function(para1, para2, “…”);
By using the first one, you are creating a function with a name funcname, which is actually a pointer to the function. It is called function declaration. By using the second two, you are creating a function which is widely know as a anonymous function. It is called a function expression, which returns a pointer, and you can assign it to a variable funcname so as to call(invoke) it. The diffrence between them is how the browser loads them into the execution context:
function declarations loads before any code is executed.
While function expressions loads only when the interpreter reaches that line of code.
By declaring a function, you can call it before you have actually defined. That is because javascript has the mechanisim to raise the function decalration before any code is excuted, while you cannot do that in the second situation.
Invocation
The invocation is really different from a difinition, especially in these scrtipt language. A function is never executed until it is invoked. As metioned in Javascript: The Good Parts, there are 4 paterns of invovation in javascript:
- The Method Invocation Pattern
- The Function Invocation Pattern
- The Constructor Invocation Pattern
- The Apply Invocation Pattern
The difference between them is how the special varible this is initialized.
The method invocation pattern
If an invocation expression con- tains a refinement (that is, a . dot expression or [subscript] expression), it is invoked as a method. A common patern is like:
var num = Myobject.method(para1, para2);
In this way, the bonus parameter this is bound to the object Myobject. That is when you alert(this) inside the function, it will alert Object Myobject.
The function invocation pattern
When a function is not the property of an object, then it is invoked as a function:
var sum = add(3, 4); // sum is 7
Most of the function are invoked in this way. In this case, the bonus parameter this is bound to the global object. That is when you alert(this) inside the function, it will alert Object Global(or mostly the Window object in a browser).
The constructor invocation pattern
If a function is invoked with the new prefix, then a new object will be created with a hidden link to the value of the function’s prototype member, and this will be bound to that new object. That is what confused me at the first glance, about how a constructor works in javascript which is made by a function without a class being defined. The author gave a clear answer that javascript is a prototypal inheritance language while offers an object-making syntax that is reminiscent of the classical languages.
The apply invocation pattern
The apply method lets us construct an array of arguments to use to invoke a func- tion. It also lets us choose the value of this. The apply method takes two parame- ters. The first is the value that should be bound to this. The second is an array of parameters.
To identify the differences, I will go to an overall example:Firstly, define an object:
function Person(){ };
It is just used to demonstrate the object machanism, so we actually have nothing in it.
Secondly, create an instance called p of object Person
var p = new Person();
Thirdly, create a method displayneme by assigning it a function:
p.displayname=function(){
alert(this); //object p
return function dis(){
alert(this); //window
}
}
var disp = p.displayname(); //get the pointer of the function
disp(); //invoke it
If we rearrange the order of the code to:
var p = new Person();
var disp = p.displayname(); //get the definition of the function
disp(); //invoke it, error occurs
p.displayname=function(){
alert(this);
return function dis(){
alert(this);
}
}
function Person(){
}
It will alert an error that Person has no method displayname, but we can still create the p instance before we define an object Person. That is because the constructor function isn raised before the code is executed, while the function p.displayname is loaded when the interpreter reaches that line.
If we look at how the alert box shows us the this parameter, we can easily know that the inside the first function, p.displayname, this = object p, while in the second function, dis(), this = global object window. The second function, which is invoked in a function patern, it just doesn’t have the access to the object p.
Another way to invoke that inner function is:
p.displayname=function(){
alert(this); //object p
return function dis(){
alert(this); //window
}(); // invoke directly
}
p.displayname(); //get the pointer of the function
The function about is called a self-invoking function, by adding a () after the definition of the function. In this way, we don’t need to assign the inner function to a variable disp to invoke it, and get the result in the inner function.