A deep understanding of javascript scopes and closures, and a deep understanding of javascript

Source: Internet
Author: User

A deep understanding of javascript scopes and closures, and a deep understanding of javascript

Scope

Scope is the scope of a variable and function. All variables declared in the function in javascript are always visible in the function body, and global and local scopes are available in javascript, however, there is no block-level scope, and the priority of local variables is higher than that of global variables, you can use several examples to understand the "hidden rules" in javascript (these are also frequently asked questions during front-end interviews ).

1. Variable declaration in advance
Example 1:

var scope="global";function scopeTest(){  console.log(scope);  var scope="local" }scopeTest(); //undefined

The output here is undefined, and no error is reported, because the Declaration in the function we mentioned earlier is always visible in the function body. The above function is equivalent:

var scope="global";function scopeTest(){  var scope;  console.log(scope);  scope="local" }scopeTest(); //local

Note: If you forget var, the variable is declared as a global variable.

2. No block-level scope

Unlike other common languages, Javascript does not have block-level scopes:

Function scopeTest () {var scope ={}; if (scope instanceof Object) {var j = 1; for (var I = 0; I <10; I ++) {// console. log (I);} console. log (I); // output 10} console. log (j); // output 1}

In javascript, the scope of a variable is function-level, that is, all the variables in the function are defined in the entire function, this also brings about some "Hidden Rules" that we will encounter when we are not paying attention ":

var scope = "hello";function scopeTest() {  console.log(scope);//①  var scope = "no";  console.log(scope);//②}

At ①, the output value is undefined. it's just crazy. We have defined the global variable value. Shouldn't it be hello? In fact, the above Code is equivalent:

var scope = "hello";function scopeTest() {  var scope;  console.log(scope);//①  scope = "no";  console.log(scope);//②}

Declaration advance and the priority of global variables is lower than that of local variables. Based on these two rules, it is not difficult to understand why undefined is output.

Scope chain

In javascript, each function has its own execution context. When the code is executed in this environment, the scope chain of the variable object is created, the scope chain is an object list or object chain, which ensures orderly access to variable objects.
The frontend of the scope chain is the variable object of the current code execution environment, which is often called an "active object". The variable search starts from the object of the first chain. If the object contains the variable attribute, then stop searching. If not, it will continue to search for the upper-level scope chain until it finds the global object:

The step-by-step query of the scope chain also affects the program performance. The longer the scope chain of variables, the greater the impact on the performance. This is also the main reason we try to avoid using global variables.

Closure

Basic Concepts
Scope is a prerequisite for understanding the closure. Closure refers to the ability to always access variables in the external scope within the current scope.

function createClosure(){  var name = "jack";  return {    setStr:function(){      name = "rose";    },    getStr:function(){      return name + ":hello";    }  }}var builder = new createClosure();builder.setStr();console.log(builder.getStr()); //rose:hello

In the above example, two closures are returned in the function, both of which maintain reference to the external scope. Therefore, no matter which call, the variables in the external function can always be accessed. The function defined in a function adds the active objects of external functions to its own scope chain. Therefore, the internal functions in the above instance can access the attributes of external functions, this is also a way for javascript to simulate private variables.

Note: Because the closure has additional function scopes (internal anonymous functions carry external function scopes), the closure occupies more memory space than other functions, excessive use may increase memory usage.

Variables in the closure

When using the closure, the closure can only obtain the last value of the internal function due to the impact of the scope chain mechanism. This causes a side effect that if the internal function is in a loop, the value of the variable is always the last value.

// This instance is not reasonable and has some latency factors. Here, we mainly explain the problems in the closure loop function timeManage () {for (var I = 0; I <5; I ++) {setTimeout (function () {console. log (I) ;}, 1000 )};}

The above program did not input 1-5 numbers as we expected, but all output 5 times. Let's look at an example:

function createClosure(){  var result = [];  for (var i = 0; i < 5; i++) {    result[i] = function(){      return i;    }  }  return result;}

Call createClosure () [0] () to return 5 and createClosure () [4] () to return 5. Through the above two examples, we can see that the closure has problems in the use of internal functions with loops: because each function's scope chain stores active objects for external functions (timeManage, createClosure, therefore, they all reference the same variable I. When an external function returns, the I value is 5, so the value of each internal function I is also 5.
How can this problem be solved? We can use the anonymous package (anonymous self-execution function expression) to forcibly return the expected results:

function timeManage() {  for (var i = 0; i < 5; i++) {    (function(num) {      setTimeout(function() {        console.log(num);      }, 1000);    })(i);  }}

Or return an anonymous function value in the closure anonymous function:

Function timeManage () {for (var I = 0; I <10; I ++) {setTimeout (function (e) {return function () {console. log (e) ;}) (I), 1000) }// timeManager (); outputs 1, 2, 3, 4, 5 Functions createClosure () {var result = []; for (var I = 0; I <5; I ++) {result [I] = function (num) {return function () {console. log (num) ;}} (I) ;}return result ;}// createClosure () [1] () Output 1; createClosure () [2] () Output 2

Whether it is an anonymous package or a nested anonymous function, in principle, because the function is passed by value, the value of variable I is copied to the real parameter num, an anonymous function is created inside the anonymous function to return num, so that each function has a copy of num, which does not affect each other.

This in the closure

When using this in the closure, you should pay special attention to it. A slight carelessness may cause problems. Generally, we understand that this object is bound based on functions during runtime. In Global functions, this object is a window object. When a function is called as a method in an object, this is equal to this object (TODO does a sorting on this ). Since the scope of an anonymous function is global, this of the closure usually points to the Global Object window:

var scope = "global";var object = {  scope:"local",  getScope:function(){    return function(){      return this.scope;    }  }}

Call object. the returned value of getScope () is global rather than the expected local. We have mentioned that the internal anonymous function in the closure will carry the scope of the external function. Why didn't we get this of the external function? When each function is called, this and arguments are automatically created. When an internal anonymous function is searching, it finds that the active object contains the expected variable, so it stops searching for the external function, it is never possible to directly access variables in external functions. In short, when a function in a closure is called as a method of an object, pay special attention to the fact that this of the internal anonymous function of this method points to a global variable.

Fortunately, we can solve this problem very easily. We only need to store this of the external function scope in a variable that can be accessed by the closure:

Var scope = "global"; var object = {scope: "local", getScope: function () {var that = this; return function () {return that. scope ;}} object. getScope () returns local.

Memory and Performance

Because the closure contains the same scope Chain Reference as the context in the function runtime, it will have a negative effect. When the active objects in the function and the runtime context are destroyed, because it is necessary to still reference the active object, the active object cannot be destroyed, which means that the closure occupies more memory space than the normal function, memory leakage may also occur in IE browsers, as shown below:

 function bindEvent(){  var target = document.getElementById("elem");  target.onclick = function(){    console.log(target.name);  } }

In the preceding example, an anonymous function generates a reference to the external object target. If an anonymous function exists, the reference will not disappear, and the target object of the external function will not be destroyed, this produces a circular reference. The solution is to reduce circular references to external variables and manually reset objects by creating a target. name copy:

 function bindEvent(){  var target = document.getElementById("elem");  var name = target.name;  target.onclick = function(){    console.log(name);  }  target = null; }

If there is access to external variables in the closure, the search path of the identifier is undoubtedly added. Under certain circumstances, this will also cause performance loss. The solution to this problem has previously been mentioned: store external variables into local variables as much as possible to reduce the search length of the scope chain.

Summary: closures are not unique to javascript, but they have their own unique forms. With closures, we can define private variables in javascript, or even mimic block-level scopes, but in the process of using the closure, we also need to understand the existing problems so as to avoid unnecessary problems.


I want to learn more about the javascript operating mechanism, such as closures, prototype chains, and scopes. What books do I recommend?

The above two authoritative guides and advanced programming can be viewed.

I recommend the essence of the javascript language written by Zhou aimin

Javascript Closure

The js closure problem is actually the scope of js variables. js has two scopes: global scope and function scope, so the global scope will not be mentioned, closures are actually a feature derived from function scopes. because each function has a scope, a scope chain exists. For example:
Var a = "";
Function test0 (){
Var B = "B ";
Function test1 (){
Var c = "c ";
Return a + B + c;
}
}
In this way, a scope chain has a global scope ==> test0 function scope ==> test1 function scope, so that the test1 function can obtain the values of test0 and global variables, that is, the values of a and B can be obtained. The test0 function can obtain the global variable value, that is, the value following the scope chain can be obtained. in fact, the closure refers to this feature of the scope chain.
However, closures are generally used on anonymous functions. The above functions can be changed to the following
Var a = "";
Function test0 (){
Var B = "B ";
Return function (){
Var c = "c ";
Return a + B + c;
}
}
Test0 (); // => "abc"
I hope it will help you

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.