Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
112 views
in Technique[技术] by (71.8m points)

javascript - JavaScript闭包如何工作?(How do JavaScript closures work?)

How would you explain JavaScript closures to someone with a knowledge of the concepts they consist of (for example functions, variables and the like), but does not understand closures themselves?

(您将如何向了解其闭包概念(例如函数,变量等)的人解释JavaScript闭包,但却不了解闭包本身?)

I have seen the Scheme example given on Wikipedia, but unfortunately it did not help.

(我已经在Wikipedia上看到了Scheme示例 ,但是不幸的是它没有帮助。)

  ask by community wiki translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

JavaScript closures for beginners(面向初学者的JavaScript关闭)

Submitted by Morris on Tue, 2006-02-21 10:19.

(莫里斯在2006年2月2日星期二提交。)

Community-edited since.

(从此开始由社区编辑。)

Closures are not magic(关闭不是魔术)

This page explains closures so that a programmer can understand them — using working JavaScript code.

(本页说明了闭包,以便程序员可以使用有效的JavaScript代码来理解闭包。)

It is not for gurus or functional programmers.

(它不适用于专家或功能性程序员。)

Closures are not hard to understand once the core concept is grokked.

(一旦核心概念浮出水面,关闭就不难理解。)

However, they are impossible to understand by reading any theoretical or academically oriented explanations!

(但是,通过阅读任何理论或学术上的解释是不可能理解它们的!)

This article is intended for programmers with some programming experience in a mainstream language, and who can read the following JavaScript function:

(本文面向具有某种主流语言编程经验并且可以阅读以下JavaScript函数的程序员:)

 function sayHello(name) { var text = 'Hello ' + name; var say = function() { console.log(text); } say(); } sayHello('Joe'); 

Two brief summaries(两篇摘要)

  • When a function ( foo ) declares other functions (bar and baz), the family of local variables created in foo is not destroyed when the function exits.

    (当一个函数( foo )声明其他函数(bar和baz)时,在该函数退出时,在foo创建的局部变量族不会被破坏 。)

    The variables merely become invisible to the outside world.

    (这些变量只是对外界不可见。)

    foo can therefore cunningly return the functions bar and baz , and they can continue to read, write and communicate with each other through this closed-off family of variables ("the closure") that nobody else can meddle with, not even someone who calls foo again in future.

    (因此, foo可以巧妙地返回功能barbaz ,并且它们可以通过这个封闭的变量家族(“闭包”)继续进行读取,写入和通信,这些变量是其他任何人都无法干预的,甚至没有人可以介入foo再来一次。)

  • A closure is one way of supporting first-class functions ;

    (闭包是支持一流功能的一种方式。)

    it is an expression that can reference variables within its scope (when it was first declared), be assigned to a variable, be passed as an argument to a function, or be returned as a function result.

    (它是一个表达式,可以引用其范围内的变量(首次声明时),分配给变量,作为参数传递给函数或作为函数结果返回。)

An example of a closure(闭包的例子)

The following code returns a reference to a function:

(以下代码返回对函数的引用:)

 function sayHello2(name) { var text = 'Hello ' + name; // Local variable var say = function() { console.log(text); } return say; } var say2 = sayHello2('Bob'); say2(); // logs "Hello Bob" 

Most JavaScript programmers will understand how a reference to a function is returned to a variable ( say2 ) in the above code.

(大多数JavaScript程序员将理解上面代码中如何将对函数的引用返回到变量( say2 )。)

If you don't, then you need to look at that before you can learn closures.

(如果不这样做,那么您需要先研究一下闭包。)

A programmer using C would think of the function as returning a pointer to a function, and that the variables say and say2 were each a pointer to a function.

(使用C的程序员会将函数视为返回函数的指针,并且变量saysay2分别是函数的指针。)

There is a critical difference between a C pointer to a function and a JavaScript reference to a function.

(指向函数的C指针和指向函数的JavaScript引用之间存在关键区别。)

In JavaScript, you can think of a function reference variable as having both a pointer to a function as well as a hidden pointer to a closure.

(在JavaScript中,你可以把一个函数引用变量作为既具有指针功能以及一个隐藏的指针关闭。)

The above code has a closure because the anonymous function function() { console.log(text); }

(上面的代码已关闭,因为匿名函数function() { console.log(text); })

function() { console.log(text); } is declared inside another function, sayHello2() in this example.

(function() { console.log(text); } 另一个函数内部声明,在此示例中为sayHello2() 。)

In JavaScript, if you use the function keyword inside another function, you are creating a closure.

(在JavaScript中,如果在另一个函数中使用function关键字,则将创建一个闭包。)

In C and most other common languages, after a function returns, all the local variables are no longer accessible because the stack-frame is destroyed.

(在C和其他大多数常用语言,函数返回 ,因为堆栈帧被摧毁了所有的局部变量都不再使用。)

In JavaScript, if you declare a function within another function, then the local variables of the outer function can remain accessible after returning from it.

(在JavaScript中,如果在另一个函数中声明一个函数,则外部函数从其返回后仍可访问。)

This is demonstrated above, because we call the function say2() after we have returned from sayHello2() .

(上面已经演示了这一点,因为我们从sayHello2()返回后调用了函数say2() sayHello2() 。)

Notice that the code that we call references the variable text , which was a local variable of the function sayHello2() .

(请注意,我们调用的代码引用了变量text ,这是函数sayHello2()局部变量 。)

function() { console.log(text); } // Output of say2.toString();

Looking at the output of say2.toString() , we can see that the code refers to the variable text .

(查看say2.toString()的输出,我们可以看到该代码引用了变量text 。)

The anonymous function can reference text which holds the value 'Hello Bob' because the local variables of sayHello2() have been secretly kept alive in a closure.

(匿名函数可以引用包含值'Hello Bob' text ,因为sayHello2()的局部变量已在闭包中秘密保持活动状态。)

The genius is that in JavaScript a function reference also has a secret reference to the closure it was created in — similar to how delegates are a method pointer plus a secret reference to an object.

(天才之处在于,在JavaScript中,函数引用还具有对其创建于其内的闭包的秘密引用—类似于委托如何成为方法指针以及对对象的秘密引用。)

More examples(更多例子)

For some reason, closures seem really hard to understand when you read about them, but when you see some examples, it becomes clear how they work (it took me a while).

(由于某些原因,当您阅读闭包时,似乎真的很难理解它,但是当您看到一些示例时,很清楚它们是如何工作的(花了我一段时间)。)

I recommend working through the examples carefully until you understand how they work.

(我建议仔细研究这些示例,直到您理解它们的工作原理。)

If you start using closures without fully understanding how they work, you would soon create some very weird bugs!

(如果您在不完全了解闭包工作原理的情况下开始使用闭包,那么您很快就会创建一些非常奇怪的错误!)

Example 3(例子3)

This example shows that the local variables are not copied — they are kept by reference.

(此示例显示局部变量未复制-通过引用保留它们。)

It is as though the stack-frame stays alive in memory even after the outer function exits!

(似乎即使外部函数退出后,堆栈框架仍在内存中保持活动状态!)

 function say667() { // Local variable that ends up within closure var num = 42; var say = function() { console.log(num); } num++; return say; } var sayNumber = say667(); sayNumber(); // logs 43 

Example 4(例子4)

All three global functions have a common reference to the same closure because they are all declared within a single call to setupSomeGlobals() .

(这三个全局函数都对同一闭包有共同的引用,因为它们都在一次调用setupSomeGlobals() 。)

 var gLogNumber, gIncreaseNumber, gSetNumber; function setupSomeGlobals() { // Local variable that ends up within closure var num = 42; // Store some references to functions as global variables gLogNumber = function() { console.log(num); } gIncreaseNumber = function() { num++; } gSetNumber = function(x) { num = x; } } setupSomeGlobals(); gIncreaseNumber(); gLogNumber(); // 43 gSetNumber(5); gLogNumber(); // 5 var oldLog = gLogNumber; setupSomeGlobals(); gLogNumber(); // 42 oldLog() // 5 

The three functions have shared access to the same closure — the local variables of setupSomeGlobals() when the three functions were defined.

(这三个函数具有对同一个闭包的共享访问权限-定义了三个函数时, setupSomeGlobals()的局部变量。)

Note that in the above example, if you call setupSomeGlobals() again, then a new closure (stack-frame!) is created.

(请注意,在上面的示例中,如果再次调用setupSomeGlobals() ,则会创建一个新的闭包(堆栈框架!)。)

The old gLogNumber , gIncreaseNumber , gSetNumber variables are overwritten with new functions that have the new closure.

(旧的gLogNumbergIncreaseNumbergSetNumber变量将被具有新闭包的函数覆盖。)

(In JavaScript, whenever you declare a function inside another function, the inside function(s) is/are recreated again each time the outside function is called.)

((在JavaScript中,每当在另一个函数中声明一个函数时,每次调用外部函数时都会重新创建一个 (或多个)内部函数。))

Example 5(例子5)

This example shows that the closure contains any local variables that were declared inside the outer function before it exited.

(此示例显示闭包包含退出前在外部函数内部声明的任何局部变量。)

Note that the variable alice is actually declared after the anonymous function.

(请注意,变量alice实际上是在匿名函数之后声明的。)

The anonymous function is declared first and when that function is called it can access the alice variable because alice is in the same scope (JavaScript does variable hoisting ).

(首先声明匿名函数,并在调用该函数时可以访问alice变量,因为alice在同一作用域内(JavaScript进行变量提升 )。)

Also sayAlice()() just directly calls the function reference returned from sayAlice()</c

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...