How to understand the scope of JS, closures, private variables, the This object concept?
Let's start with a classic face test!
Title: Create 10 <a> tags, click time to pop up the corresponding serial number
Think about it, then open it.
// think about what you're going to write about, isn't it? But the result, the bounce is 10, why? var i,a for (i=0;i<10;i++) { a=document.createelement (' A ') a.innerhtml=i+ ' <br> ' a.addeventlistener (' click ',function (event) { var event=event| | window.event event.preventdefault () alert (i) }) Document.body.appendChild (a) }
View Code
The answer to this question at the end, of course, you can go straight to the end to understand, but I do not recommend this!!
Related to today's variables, scopes, closures and so on, in the variables, scope of knowledge has been said some, and then re-simple to say.
execution Environment : Also known as the execution context, two, one is the Global Environment (window), one is the function environment (each function is a function environment)
Scope chain : Contemporary code executes in an environment, creating a scope chain of variable objects to guarantee orderly access to all variables and functions that the execution environment has access to. The external environment is inaccessible to the internal environment, and the internal environment can be accessed through the scope chain.
block-level scope : JS has no block-level scope, similar to the loop statement, conditional judgment statement within the scope is global; only two execution environments
variable : The var operator determines whether it is a local variable or a global variable.
Browser parsing: In the browser parsing, all the variables are promoted first, the variables are saved as undefined, when the execution of the line to give the assignment; the function declaration is complete at the beginning, and the function expression is the same as the parse variable.
Console.log (a) //undefined var a=100 console.log (a) //100 Person ("double") //double,20 functions Person (name) {//Declaration function Age =20 console.log (name,age) var }
This: the object that references the execution environment, which can be confirmed only at execution time and cannot be confirmed when defined
//an ordinary constructor; This is an instance of a constructor function . functionFoo (name) {//var this This. name=name//return This } varf=NewFoo ("Double") //ordinary object; This is the object. varobj={name:"Double", Printname:function() {Console.log ( This. Name)} } obj.printname ()//normal function This is the window functionfn () {Console.log ( This)} fn ()//Call apply bind to set the value of this functionfn1 (name,age) {alert (name) Console.log ( This)} fn1.call ({x:[+], ' double ', 20)//This is the object {x:100}Fn1.apply ({x:100},["double", 20])//This is the object {x:100} varFn2=function(name,age) {alert (name) Console.log ( This)}.bind (' Double ', 20)//this is double.FN2 ()
Closed Package
This concept is somewhat abstract, so to understand: a function that has access to a variable in another function scope, which means that one function can access a variable in another function scope
Generally two places, one as the return value, one as the passed parameter
//Closed Package//function as return valuefunctionF1 () {vara=100; //returns a function (function as return value) return function(){Console.log (A)}}//F1 get a functionvarf1=F1 ()vara=200F1 ()//a=100 executes the return function, and the function finds the variable (not the scope of the executing function) in the scope of the defined function, and does not find the parent scope//function as a parameter passfunctionF1 () {vara=100return function() {Console.log (A)}}varF1=F1 ()//It's a function .functionF2 (FN) {vara=200fn ()} F2 (F1)//a=100 to the function to F2
Take the closure as the return value as an example, say a little bit more
This is an example of a closure to return a value
functionCreate () {vara=100return function() {Console.log (A)}}vara=200varResult=create ()//Get Return functionResult ()//executing the return function The A=100 function looks in the scope of the defined function and then finds it in the parentwhen a function is called, an execution environment and the corresponding scope chain are created, the active object of the function is initialized with arguments and other parameters, but in the scope chain, the active object of the outer function is always the second, and for the anonymous function inside the CREATE function, the The domain chain is initialized with three active objects, one for itself, one for the CREATE function, and one for the global environment. In general, the function is executed and the active object is destroyed; But for closures, when the CREATE function finishes, the active object of the function is not destroyed. Because the internal anonymous function always references the active object in it
Look at this again.
//a method of a normal object varperson={name:"Double", GetName:function() {Console.log ( This. Name)} } person.getname ()//Double //the Normal object method returns an anonymous function varperson={name:"Double", GetName:function(){ return function() {Console.log ( This. Name)} } } varName= "single"Person.getname () ()// Single //the Normal object method returns an anonymous function varperson={name:"Double", GetName:function(){ varthat= This //The variable assigned to that by this object before the anonymous function is defined is about the same as this and arguments, and assigns it to a variable return function() {Console.log (That.name)}}} varName= "single"Person.getname () ()//Double
OK, after understanding the closure, scope chain knowledge, back to the interview question, you should know the reason
The correct wording
varI for(i=0;i<10;i++){ (function(i) {varA=document.createelement (' a ') a.innerhtml=i+ ' <br> 'A.addeventlistener (' Click ',function(event) {varevent=event| |window.event Event.preventdefault () alert (i)//go to Parent scope lookup}) Document.body.appendChild (A)}) (i)}//JS has no block-level scope, so I of alert (i) is in the global scope, and the return is of course ten, //How do I let I bounce out of each one? //we know that the environment is divided into functional environment and global environment, only need to have their own execution environment for each I can //How do you do that? //directly add a self-executing function, so that each i has its own function environment, that is, to build a private scope
Memory leaks
Because of the existence of closures, the variables of the external function are always referenced, the closure does not end, the reference is always present, and the memory is not recycled
//Memory Leaks functionPerson () {varElement=document.getelementbyid ("Someelement") Element.onclick=function() {alert (element.id)}}//Resolving memory leaks functionPerson () {varElement=document.getelementbyid ("Someelement") varId=element.id//assign the required content to a variableelement.onclick=function() {Alert (id)} element=NULL //The closure refers to the entire active object containing the function, which contains the element}
Mimic block-level scopes
All know, JS does not block-level scope, so to imitate, how to imitate it?
The above-mentioned question has been told: the function environment is constructed by an anonymous function to form a private scope
The following explains something about anonymous functions, function declarations, function expressions, description of block-level scopes
//A variable name is just another form of a value varcount=10alert (count) alert (10) //since the variable is possible, what about the function? varperson=function() {alert ("Hello")} person ()varperson=function() {alert ("Hello") }() function() {alert ("Hello") }() //Error //why not? Because JS takes the function keyword as the start of a declaration of functions, the function declaration cannot be parenthesized (function() {alert ("Hello") })() //To convert a function declaration to a function expression, you can add parentheses to the outside, that is, to form your own private scope
Read Uncle Tom's blog about this, and he said so.
//conversions for function declarations and function expressions //JS bracket () is not included in the statement, and JS in the &&,| |, comma and other operators are in function expressions and function declarations to disambiguate //so varI=function() {Console.log ("Hello")}() true&&function() {Console.log ("Hello")}() 0,function() {Console.log ("Hello")}() !function() {Console.log ("Hello")}() ~function() {Console.log ("Hello")}() -function() {Console.log ("Hello")}() +function() {Console.log ("Hello")}() New function() {Console.log ("Hello")} varvalue=10New function() {Console.log (value)} (value)//Parentheses Pass Parameters
So much for the knowledge of closures.
Parsing the scope and closure of JS--starting with a classic face question