Home  >  Article  >  Web Front-end  >  JS closures and applications that front-end development must know_javascript skills

JS closures and applications that front-end development must know_javascript skills

WBOY
WBOYOriginal
2016-05-16 18:23:46835browse

In the article JS Prototype and Inheritance that front-end development must know, I mentioned that I will write an article on closures. In addition, I have recently found that I need to strengthen my closure application capabilities, so this article cannot be postponed any longer. This article talks about function closures and does not involve object closures (such as using with). If you think what I said is wrong, please feel free to comment and give me advice.
1. The theory of closure
First of all, you must understand the following concepts:

Execution environment
Every time a function is called (when the function is executed), the system will Create a closed local running environment for the function, which is the execution environment of the function. Functions are always executed in their own execution environment, such as reading and writing local variables, function parameters, and running internal logic. The process of creating an execution environment includes creating the scope of the function, and the function is also executed in its own scope. From another perspective, each function execution environment has a scope chain, and the scope chain of the child function includes the scope chain of its parent function. Please see below for scope and scope chain.

Scope, scope chain, calling object
Function scope is divided into lexical scope and dynamic scope.
Lexical scope is the scope when the function is defined, that is, static scope. When a function is defined, its lexical scope is determined. The lexical scope describes the scope of the function under the nested relationship of the function structure. At this time, the scope chain of the function is formed. The scope chain is to connect these scopes with nested hierarchical relationships. The function's internal [[scope]] attribute points to this scope chain.
Dynamic scope is the scope when a function call is executed. When a function is called, the [[scope]] attribute inside the function is first pointed to the scope chain of the function, and then a calling object is created, and the calling object is used to record the function parameters and local variables of the function, and put them in the scope chain. Top of domain chain. Dynamic scope is created by adding the calling object to the top of the scope chain. At this time, [[scope]] not only has the scope chain when it is defined, but also has the calling object created when it is called. In other words, the scope in the execution environment is equal to the scope chain determined when the function was defined plus the calling object just created by the function, thus forming a new scope chain. So it is a dynamic scope, and the scope chain also changes accordingly. Looking at the scope here, it is actually an object chain. These objects are the calling objects created when the function is called, and the calling objects above it until the top-level global object.
For example, if function A in the global environment has a function B nested within it, then the scope chain of function B is: the scope of function B -> the scope of function A -> the scope of the global window. When function B is called, when looking for an identifier, it will be searched according to the scope of function B -> the scope of function A -> the scope of the global window. In fact, it will be searched according to the calling object of function B -> function The calling object of A -> global object is searched in this order. That is to say, when a function is called, the scope chain of the function is actually the calling object chain.

Closure
In a dynamic execution environment, data changes in real time. In order to maintain the values ​​of these non-persistent variables, we use closures as a carrier to store these dynamic data (read the following You will understand this sentence very well if you apply it). Definition of closure: The so-called "closure" refers to an expression (usually a function) that has many variables and an environment bound to these variables, so these variables are also part of the expression.
A closure is an internal function nested inside a function, and the internal function can access all local variables, parameters and other internal functions declared in the external function. When the inner function is called outside the outer function, a closure is generated. (In fact, any function is an internal function of the global scope and can access global variables, so it is a closure of window)
 For example, the following example:

Copy code The code is as follows:



Garbage collection mechanism: If an object is no longer referenced, the object will be recycled.
Combining some of the concepts mentioned above, the calling object of f is created when executing var test=f(1). Let’s call it obj here. Although the external execution environment exits after execution, the internal function inner is A variable test reference outside the external function f. Since the calling object obj created by the external function has an attribute pointing to this internal function, and now this internal function is referenced, the calling object obj will continue to exist and will not be recycled by the garbage collector. Its function parameter x and local variable a will maintained in this calling object. Although the calling object cannot be directly accessed, the calling object has become part of the internal function scope chain and can be accessed and modified by the internal function, so when test() is executed, x and a can be accessed correctly. So, when the external function is executed, the closure is generated, and the variables of the external function referenced will continue to exist.
2. Application of closure
Application 1:
This is a problem I encountered while using js to simulate the sorting algorithm. I want to output the sorted array after each insertion. If it is written in the loop as
 setTimeout(function() { $("proc").innerHTML = arr "
"; }, i * 500) ;
You will find that each output is the final sorted array, because the arr array does not retain the status value of each sort for you. In order to save the constantly changing array values, we wrap a layer of functions outside to implement closures, and use closures to store this dynamic data. Two methods are used to implement closures below. One is to use parameters to store the value of the array, and the other is to use temporary variables to store the value. The latter must be deep copied. All non-persistent variables that need to be stored through closures can be implemented in two ways: temporary variables or parameters.

[Ctrl A Select all Note: If you need to introduce external Js, you need to refresh to execute
]

Application 2:
This is an example on Wuyou (click here to view the original post), which binds the click event popup loop index value to each
  • node. Originally written as
    id.onclick = function(){ alert(i); } id.onclick = function(){alert(i);}
    I found that the final popup was 4, not the desired 1 , 2, 3, because the i value becomes 4 after the loop is completed. In order to save the value of i, we also use closure:

    [Ctrl A Select all Note:
    If you need to introduce external Js, you need to refresh to execute
    ]

    (ps: var a = (function(){})(); has the same effect as var a =new function(){}, both represent self-executing functions)
    Application 3:
    The following code is a cache application, catchNameArr. . The value of catch is saved in the calling object of the anonymous function. Since the returned object is referenced by the CachedBox variable, the calling object of the anonymous function will not be recycled, thus retaining the value of catch. It can be operated through CachedBox.getCatch("regionId");. If the regionId cannot be found, it will be fetched from the background. The catchNameArr is mainly to prevent the cache from being too large. Copy code
    The code is as follows:



    同理,也可以用这种思想实现自增长的ID。  
    复制代码 代码如下:



    应用4:
      这个是无忧上月MM的例子(点击这里查看原帖),用闭包实现程序的暂停执行功能,还蛮创意的。

    [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

    把这个作用延伸下,我想到了用他来实现window.confirm。

    [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

    看了上面的这些应用,再回到前面的一句话:在动态执行环境中,数据实时地发生变化,为了保持这些非持久型变量的值,我们用闭包这种载体来存储这些动态数据。这就是闭包的作用。也就说遇到需要存储动态变化的数据或将被回收的数据时,我们可以通过外面再包裹一层函数形成闭包来解决。
      当然,闭包会导致很多外部函数的调用对象不能释放,滥用闭包会使得内存泄露,所以在频繁生成闭包的情景下我们要估计下他带来的副作用。
      毕了。希望能对大家有所帮助。
    者:JayChow
    出处:http://ljchow.cnblogs.com
  • Statement:
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn