Problem background: Because of the existence of the closure in JS and the particularity of this, it is often impossible to determine the value of the variable.
A Variables in closures
Example 1.
- var name= "thewindow";
- var getname= (function () {
- var name = "My function";
- return function () {
- return name;
- }
- })();
- Console.log (GetName ()); //my function
- Console.log (name); The Window
- Getname=null; Remove the reference to the anonymous function and release the excess memory occupied by the closure
The concept of closure in JS is that closures are functions that have access to variables in another function scope.
In Example 1, the getname right-hand function expression is an immediate execution function and returns an anonymous function, which is a closure. For a normal function, it will release its occupied memory after execution, but it is not the case for closures. GetName is the anonymous function returned, which is useful to the name of an external anonymous function, so immediately after execution of the function is not free of memory, it must be determined that the closure can not be executed again in case the memory is freed (the reason that the closure consumes a lot of memory).
Why CODE5 's name is parsed into my function and Code10 is parsed into the window?
This will be said from the execution environment (execution context, commonly known as "contexts"), when the code executes in the execution environment, first create the variable object, and then create a variable object (VO) a scope chain, to ensure that the execution environment has access to all variables and functions of the orderly access. The front end of the scope chain is always a variable object in the execution environment where the code is currently executing, and the next variable object comes from the next variable object that contains the execution environment, which continues to the Global Execution Environment (window). The parsing of identifiers is also parsed from the front end of the scope chain (the VO of the current execution environment) to the end of the scope chain (VO for the Global Execution Environment). It is important to look at the scope of the variable, as long as it is in the scope chain of the execution environment where it resides. ------Because the function execution environment is special, its variable object is called the active object (AO). The global execution environment is special, and its variable objects always exist!
Executes GetName (), where name is the scope chain of the execution environment (the closure function execution environment) that contains itself (that is, the closure function) of the active object, the outer function (that is, the immediate execution function) of the active object, the global variable object, the search from inside Out, and the name definition from the External function activity object. Executes Console.log (name), where name is the scope chain of the execution environment (global execution Environment) that contains only global variable objects from which the name definition is found.
Example 2.
- var result = [];
- function Createfunctions () {
- For (var i=0; i<3; i++) {
- Result[i]=function () {
- return i;
- };
- }
- }
- Createfunctions ();
- Console.log (Result[0] ()); //3
- Console.log (Result[1] ()); //3
- Console.log (Result[2] ()); //3
This configuration mechanism of the scope chain causes closures to only get the last value of any variable that contains the function!
Workaround:
- var result = [];
- function Createfunctions () {
- For (var i=0; i<3; i++) {
- Result[i]= (function (num) {
- return function () {
- return num;
- };
- }) (i);
- }
- }
- Createfunctions ();
- Console.log (Result[0] ()); //0
- Console.log (Result[1] ()); //1
- Console.log (Result[2] ()); //2
Use 3 immediate functions to give each function () {return num}, make a closure, save a copy of I into NUM, and have a copy of 3 I, respectively, 0,1,2,result[i] to take the corresponding copy.
Extension: Since there is no concept of block scope in JS, you can use the immediate execution function to make block scopes through the mechanism of closures!
Example 3.
- /*JS no block-level scope causes local variables to affect global variables */
- i=2;
- for (var i=0;i<4;i++) {}
- alert (i); //4
Example 4.
- /* Use the immediate execution function to mimic block-level scopes with the closure mechanism, without affecting the external variables */
- i=2;
- (function () {
- for (var i=0;i<4;i++) {}
- })();
- alert (i); //2
Two The particularity of this
Let's start with a simple example:
Example 5.
- var name= "thewindow";
- var object = {
- Name: "My Object",
- GetName:function () {
- var name = "My Function";
- return this . Name
- }
- }
- Console.log (Object.getname ()); //my Object
- Console.log ((Object.getname) ()); //my Object
- Console.log ((object.getname = Object.getname) ()); //the Window
This is based on the execution environment binding: In the global function, this refers to the window; When the function is called as an object method, this refers to the object;
Code10 and Code11 the same way, better understanding. (Note: this. is the attribute, var name= "My function" in getname cannot be understood to add a property to the function name and the value of the property is "my function"!) )
Code12 people may be more confused, why not output "My object"?
- Console.log ((object.getname = Object.getname) ()); //the Window
(Object.getname = object.getname) The meaning of this function expression is:
1. Set the GetName property/method for object.
2. Assign the value of Object.getname to it
3. Therefore the value of the expression is the function itself: functions () {var name = "My funcition"; return this.name;}
Equivalent to:
- Console.log (function () {var name = "My function"; return this.name;}) ()); //the Window
Global function, this is window, so this.name is "the window"!
Example 6.
- var name= "thewindow";
- var object = {
- Name: "My Object",
- GetName:function () {
- return function () {
- return this . Name
- };
- }
- }
- Console.log (Object.getname ()); //the Window
- Console.log ((object.getname = Object.getname) () ()); //the Window
anonymous function is special, this refers to window! ;
The classification of the comparison system is in the language of JavaScript, which is divided into function invocation pattern (This binding Global object window) and method invocation pattern (the body of the this binding called method).
It can be seen that when a function is used in a function call pattern, this is actually fixed to window! (as shown in Code11), this is actually a JS language design flaw, if the language design is correct, it should be: when the internal function is called, the inner function of this should be bound to the external function this object!
This design flaw has an easy solution:
- var name= "thewindow";
- var object = {
- Name: "My Object",
- GetName:function () {
- var = this ;
- return function () {
- return that. name;
- };
- }
- }
- Console.log (Object.getname ()); //my Object
- Console.log ((object.getname = Object.getname) () ()); //the Window
Assign the This object to the variable that, so that the closure can be taken to the external variable that (note: Each execution environment has its own this, so you have to use this method to get the external this object)
Example 7
- var name= "thewindow";
- Getname= (function () {
- var name = "My function";
- return function () {
- var name= "function";
- return this . Name
- }
- })();
- Console.log (GetName ()); //the Window
- Console.log ((GetName) ()); //the Window
Finally, check:
Code11 and Code10 are the same, code10 belong to function calls, so this refers to window
A brief talk on JS closure and the This keyword