JS language comprehension 05 closures

definition

Functions can be accessed when the context is created, called closures

Internal function has a longer life cycle than its external function

function closure(name) {
  var status = 1;
  return {
    getName: function() {
      return name;
    },
    getStatus: function() {
      return status++;
    }
  }
}
var a = closure('w3ctech');
alert(a.getName()); // w3ctech
alert(a.getStatus()); // 1
alert(a.getStatus()); // 2

Function scope:

  • Variables and parameters are not visible outside the function
  • Variables can be defined anywhere within a function, and can be seen anywhere in the function
  • Nested function parameters and variables can be accessed for external functions

Closure Scenario:

  • Achieve private members
  • Protection namespace
  • Avoid contamination global variables
  • Variables need to reside in long-term memory

Closure of understanding

Closure return is a funciton

A function in the return of a function B, C outside so when you call A, equivalent to calling the B, C are not directly access the variables A, but through B, C on a visit in the variable A

There are two purposes of closure:

  • Local variables inside a function obtained from the outside
  • Let these values ​​of local variables always exist among memory
function f1(){
    var n=999;
    function f2(){
        alert(n);//获得f1的内部变量
    }
    return f2;
}
f1()();//f1()返回值是f2,需要对f2再次引用

Defined closure: the closure (closure) is a function that can read (i.e. defined function within the function) function of his internal variables, the above example is a closure f2, f2 needs to be output as a return value inside f1 . In essence, the closure is a function of the internal and external bridge connecting function.

f1 () () a reference to the equivalent of a global variable, so where f2 exist in the global variable, and depends on the presence of f1 and f2, f1 therefore always in memory, and not at the end of the call, garbage collection mechanism (garbage collection) recovered.

Using closures to be noted that: wherein the variables present in the memory, a large memory consumption.

Questions

var name = "The Window";
var object = {
  name: "My Object",
  getNameFunc: function() {
    return function() {
      return this.name;
    };
  }
};
alert(object.getNameFunc()()); //结果 The Window

Since thisalways expressed a reference to the caller, object.getNameFunc()the return value is objectan internal object anonymous function, this function is anonymous caller window, so thisthe point is window, the last sentence is the equivalent of printing window.name, the result is'The Window'

So why not get the returned anonymous function contains its scope thisobjects?

Each function will automatically get two special variables when called, thisand arguments.Internal search function in two variables, will search until their active objects, and therefore can never directly access the external functions of two variables. But outside the scope of the thisobject stored in a variable closure can engage visited, you can make the closure of access to the object. - "JavaScript Advanced Programming" P182

var name = "The Window";
var object = {
  name: "My Object",
  getNameFunc: function() {
    var that = this;
    return function() {
      return that.name;
    };
  }
};
alert(object.getNameFunc()()); //结果My Object

that this is a value inside the object, so the result is My Object

Examples for assignment cycle

Introduced

The example below, the intention is different click li, print out the corresponding index, but the results no matter which li is clicked, the result is 3

<body>
<p title="选择你最喜欢的水果?">你最喜欢的水果是?</p>
<ul>
    <li id="li1" title="苹果">苹果</li>
    <li title="橘子">橘子</li>
    <li title="菠萝">菠萝</li>
</ul>
<script>
  var li = document.getElementsByTagName('li');
  
  for(var i= 0; i<li.length; i++){
    li[i].onclick = function(){
      alert(i)
    }
  }
</script>

JavaScript event handling mechanism

Generally, the operation is divided into: the results obtained in two steps and issues a call. Issued a call for the immediate result is synchronized. Make the call, but could not get immediate results, it requires additional operations to get the desired result is asynchronous. After the call is synchronous waits until results are returned. After the call is asynchronous, you can not directly get the result, through a series of means to finally get the result (after the call, time to get intermediate results can be involved in other tasks)

A major feature of the JavaScript language is single-threaded, user action events are asynchronous calls, such as onclick event, when onlick events are defined, it will invoke the browser corresponding API, click monitor the behavior of the corresponding object, when behavior after, the browser will this event the corresponding callback function into the task queue.

When the engine finished resolve all the statements and dom (that is, after the stack of code is completed), the main thread will be to read the task queue, followed by the implementation of those events corresponding to the callback function.

Stack code (sync task), always read "Task Queue" (asynchronous task) performed before.

Cause Analysis

There are two reasons for this will produce:

  1. Scope, JS block scope is not only a function of global scope and scope
  2. JS event handling mechanism

The above process is performed for loop as follows:

  1. Each time through the for loop, call the onclick event dom, the event was added to the task queue, adding a total of 3 click event
  2. Including all statements for execution is completed, including, when i =. 3 (when i = 2 for the last statement is executed inside, after i ++ i = 3)
  3. event loop comes into play, the polling task queue were performed
  4. At this point i in the function of the global environment i, 3 ​​are so

Solution

The closure is created using the local scope, i are passed to each function and save it inside, there are two specific methods

Method 1: Create a self-executing anonymous function will change the internal function of i incoming and saved (from execution is the key, so you do not need to be placed in a queue to wait, but in the course of execution of the cycle)

  /***利用自执行匿名函数创造一个闭包域空间,将i的值储存在函数内部
  for(var i= 0; i<li.length; i++){
    (function(j){
      li[j].onclick = function(){
        alert(j)
      }
    })(i)
  }
  ****/

Method two: is the use of closure, is to either complete the binding event in a new anonymous closure space, and this case is a function of the event binding on the new anonymous function returns

for(var i= 0; i<li.length; i++){
    li[i].onclick = (function(j){
      return function(){
        alert(j)
      }
    })(i)
  }

Method three: The use ES6 let level variable declaration block

  for(let i= 0; i<li.length; i++){
    li[i].onclick = function(){
      alert(i)
    }
  }

The reason is: let the variable i is declared, the current i is only valid in the current round of cycle, so every time i actually circulating a new variable, the final output is 6.

Hidden data with closures

Closures often used to create functions contain hidden data (but not always).

var db = (function() {
// 创建一个隐藏的object, 这个object持有一些数据
// 从外部是不能访问这个object的
var data = {};
// 创建一个函数, 这个函数提供一些访问data的数据的方法
return function(key, val) {
    if (val === undefined) { return data[key] } // get
    else { return data[key] = val } // set
    }
// 我们可以调用这个匿名方法
// 返回这个内部函数,它是一个闭包
})();

db('x'); // 返回 undefined
db('x', 1); // 设置data['x']为1
db('x'); // 返回 1
// 我们不可能访问data这个object本身
// 但是我们可以设置它的成员

reference

Guess you like

Origin blog.csdn.net/duola8789/article/details/94740144