


JavaScript allows embedded functions, allows functions to be used as data, and under the function lexical scope, it can produce surprising differences from traditional object-oriented languages.
First of all, JavaScript functions are scoped lexically, rather than dynamically. Therefore, functions run in the scope in which they are defined, not in the scope in which they are executed. , so it is easy to understand when the nested function and its surrounding function are defined in the same lexical scope. For example, the following very bland code:
var x = 'global';
function f () {
var x = 'local';
function g() {
alert(x);
}
g();
}
f(); // 'local'
When f() is called, the scope chain can be understood as consisting of two parts, including the call of f object, followed by the global object. At this time, when searching for the value of x, it will first be searched from the calling object of f. If it is not found, x will be searched for in the subsequent global object. In the same way, since g is a nested function of f, when g is called, the scope chain should consist of three parts, the calling object of g, the calling object of f, and the global object. Function g is to output the value of x, so it first searches for the value of x in the calling object of g. There is no definition in g. Then it searches for the definition of x in the peripheral f calling object, so it finds x='local', then It will output x instead of continuing to search for the global object. If the value of x is not defined in f, then it will continue to search for the global object behind the scope chain, and the result will be global. If it is not defined in the global object, then it is naturally undefined.
Okay, we have a preliminary understanding of the scope chain. At the same time, we know that closures have two common uses. One is that it can be used to access local variables, and the other is that it can be used peripherally. The variable values in the field are stored in memory and are not destroyed after the function call is completed.
Next let’s look at a mundane example, which may help understand why closures can save external variable values in memory.
function makeFunc (x) {
return function ( ) {return x }
}
var a = [makeFunc(0), makeFunc(1), makeFunc(2)];
alert(a[0]());
alert( a[1]());
alert(a[2]());
The execution results are 0,1,2; there is nothing special, this is also strict Normal behavior of lexical scope. After each makeFunc call is completed, its calling object will be removed from the scope chain, and there will no longer be any reference to it, and it will eventually be completed through garbage collection. To be more detailed, we can understand it this way.
Every time makeFunc is called, a calling object will be created for it and placed in the scope chain. For the function makeFunc, the calling object contains an attribute When the function is executed, a calling object will be created and placed in the scope chain. The anonymous function returns the value of x. (Note: There is no definition of x in the calling object of the anonymous function, so it will refer to its surrounding function. The calling object of makeFunc (accesses Since its calling object contains x, x is also destroyed when it is destroyed. Will not be saved.
The above is the detailed execution process of the function. Please understand it carefully and look at the changed code below:
var x = 0;
function makeFunc () {
return function () {return x }
}
var a = [makeFunc(), makeFunc(), makeFunc()];
alert(a[0]());
alert(a[1]());
alert(a[2]());
Now x is a global variable, and the execution results are 0, 1, 2; but this result is somewhat different from the above. Next, we will understand the reason for this result from the perspective of the scope chain.
Similarly, each time makeFunc is called, it will create a calling object into the scope chain. Since it returns a reference to the internal nested function, the internal nested function starts to execute and creates a calling object for the nested function. scope chain. Then return the value of x. Note that it is different here. There is no x in the calling object of the nested function, and there is no x in the calling object of its surrounding makeFunc. We can only search down to the global object. In the global object The definition of x is found, so it is executed normally, the value of x is returned, x is incremented by 1, then the nested function is completed, the calling object is removed, then makeFunc is completed, and the calling object is also removed, but because there is no x in their calling objects , the destruction of their calling objects will not affect x at all. As a result, the change in the value of global variable x is saved.
Note that the above-mentioned access to the outer calling object is only to help understanding and is not strict. JavaScript will not directly access the calling object in any way. However, the properties it defines are part of the scope chain in the calling object. Still "alive". In addition, if a peripheral function contains two or more nested functions that all have references to the global object, then these nested functions all share the same global calling object, and changes to the global object by one of them are visible to the others. of.
Okay, in JavaScript, a function is a complex composed of the code to be executed and the scope in which these codes are executed. Broadly speaking, we can call this complex of code and scope a closure.
【Closure】
We occasionally need to write a function that needs to be called to remember the value of a variable. Therefore, if we understand scope, we will know that local variables are difficult to achieve because the calling object of the function cannot be maintained after the call. Global variables can do this, as in the above example, but this can easily cause global variable pollution. Since the calling object cannot be maintained, shouldn't we just save the value in the calling object? ! So, here is one way to do it: save it with the properties of the function object itself.
uniqueID = function () {
if (! arguments.callee.id) arguments.callee.id = 0;
return arguments.callee.id ;
}
alert(uniqueID()); //0
alert(uniqueID()) ; //1
As above, because the function itself is an object, it is feasible for us to save it with one of its own attributes, but there is a problem with this, that is, anyone can save it at any time You can force access to the value we originally saved through unqueID.id and make modifications. This is what we don't want to see.
So, usually, we use closures to achieve this. As follows:
_uniqueID = (function(){
var id = 0;
return function () {return id }
})();
alert(_uniqueID()); //0
alert(_uniqueID()); //1
Similarly, we also use the use domain to explain the results. Notice that _uniqueID itself is an anonymous function, and there is an anonymous nested function inside it. What we call directly is _uniqueID(), that is to say, what we directly call is actually the nested function inside _uniqueID, and it The calling object itself does not define an id, so it references the id in the surrounding calling object and returns it. The id is incremented by 1. After execution is completed, the inner nested function calling object moves out of the scope chain. The peripheral ID was not destroyed, so it was saved like this.
Some people may be confused, isn’t it said that the calling object has removed the scope chain after the function is executed? The peripheral anonymous function (function(){})(); has also been called, so the calling object should not have That's right.
Yes, the calling object ends its reference after the current function is executed, but don’t misunderstand the above _uniqueID() call. It is not a directly called peripheral function, but a nested function called. The scope chain of the set of functions includes the scope chain of the surrounding function. Therefore, when its calling object removes the scope chain, it can access and change the properties of other objects in this scope chain.
Closure itself is a difficult to understand but very useful thing. I hope it can be of some help to those in need. In addition, due to limited qualifications, my understanding may be wrong. If I find it, please correct me.

闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。 换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。 闭包会随着函数的创建而被同时创建。

python闭包主要包括函数闭包和装饰器闭包。详细介绍:1、函数闭包是指在一个函数内部返回另一个函数,并且返回的函数能够访问到其内部变量。这样的返回函数就是函数闭包,函数闭包在程序中可以被反复使用,因此可以用来实现一些功能上的封装;2、装饰器闭包是指在使用装饰器时,被装饰的函数并没有直接被调用,而是被包装在一个函数内部,并返回一个新的函数。这个新的函数就是一个装饰器闭包等等。

如何利用PHP7的匿名函数和闭包实现更加灵活的代码逻辑处理?在PHP7之前,我们经常使用函数来封装一段特定的逻辑,然后在代码中调用这些函数来实现特定的功能。然而,有时候我们可能需要在代码中定义一些临时的逻辑块,这些逻辑块没有必要创建一个独立的函数,同时又不想在代码中引入太多的全局变量。PHP7引入了匿名函数和闭包,可以很好地解决这个问题。匿名函数是一种没有名

Python中的闭包是如何实现的?闭包是一种函数内部定义的函数,并且在函数内部引用了外部函数的变量。这种特性使得内部函数可以访问外部函数的变量,并且在外部函数执行完毕后,闭包仍然可以访问和操作外部函数的变量。闭包在Python中通过以下几个步骤来实现:定义外部函数,并在其中定义内部函数:首先,我们需要在外部函数内部定义一个内部函数。这个内部函数即是闭包。de

react有事件处理函数、useEffect和useCallback、高阶组件等等闭包。详细介绍:1、事件处理函数闭包:在React中,当我们在组件中定义一个事件处理函数时,该函数会形成一个闭包,可以访问组件作用域内的状态和属性。这样可以在事件处理函数中使用组件的状态和属性,实现交互逻辑;2、useEffect和useCallback中的闭包等等。

减少闭包产生的方法有避免不必要的闭包、控制闭包的返回值、使用弱引用、减少不必要的全局变量、合理使用循环和递归、使用事件代理、编写单元测试、遵循设计原则和使用工具进行代码分析等。详细介绍:1、避免不必要的闭包,在很多情况下,闭包并非必需的,可以用模块模式来实现私有变量,避免使用闭包;2、控制闭包的返回值,在使用闭包时,应该尽量控制闭包的返回值,如果闭包返回的是基本数据类型等等。

如何使用PHP7的匿名函数和闭包实现更加灵活和可复用的代码逻辑?在PHP编程领域中,匿名函数和闭包是非常有价值和强大的工具。PHP7引入了一些新的语言特性,使得使用匿名函数和闭包更加方便和灵活。本文将介绍如何使用PHP7的匿名函数和闭包来实现更加灵活和可复用的代码逻辑,并提供一些具体的代码示例。一、匿名函数匿名函数是一种没有名称的函数。在PHP中,可以将匿名

Python是一种非常流行的编程语言,因为它非常易学易用,同时也具备了强大的功能。其中,闭包是Python中的一种函数,它可以在函数的内部定义另一个函数,并返回这个函数作为函数的返回值。尽管闭包非常方便,但有时会出现某些错误,比如闭包错误。本文将介绍如何解决Python的闭包错误。初步了解闭包在Python中,闭包是由一个内部函数和一个定义在内部函数之外的函


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SublimeText3 Linux new version
SublimeText3 Linux latest version

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function

SublimeText3 Chinese version
Chinese version, very easy to use

Notepad++7.3.1
Easy-to-use and free code editor

Dreamweaver Mac version
Visual web development tools
