闭包的示例_简单地说JavaScript中的闭包(以及实际示例)

闭包的示例

Closures are special thing in the JS world. It’s time to finally understand them.

在JS世界中,闭包是很特别的事情。 现在是时候终于了解它们了。

Many agree that closures are confusing at the beginning, but once you put some time into understanding them you will find them perhaps even intuitive.

许多人都同意闭包在开始时会造成混乱,但是一旦您花了一些时间来理解它们,您可能会发现它们甚至很直观。

There are lot’s of benefits coming from understanding them i.e.:

了解它们有很多好处,即:

  • In opinion of many software leads, understanding closures is one of these things that separate the junior from the rest.

    在许多软件主管看来,了解闭包是将初中生与其他人分开的事情之一。
  • There are patterns coming from functional programming i.e. partial application that make use of closures.

    有一些来自函数式编程的模式,即使用闭包的部分应用程序

  • if you are a React girl/guy, the React Hooks rely on closures

    如果您是React女孩/家伙,那么React Hooks依赖于闭包
  • It’s almost a certain question to be asked on JavaScript job interview.

    在JavaScript求职面试中几乎要问一个问题。
  • many other benefits coming from understanding closures

    了解闭包还有很多其他好处

Yet I still see developers working for 5 and more years and ignoring the concept of closures — and they only refresh the knowledge or memorize the answers before a job interview.

但是,我仍然看到开发人员已经工作了5年以上,并且忽略了关闭的概念-他们只是在面试之前刷新知识或记住答案。

介绍 (Introduction)

Developers often learn best by tracking down the examples.

开发人员通常可以通过跟踪示例来最好地学习。

In this article we will:

在本文中,我们将:

  • cover a bit of the theory regarding JavaScript closures (just enough to be productive and understand what are we writing)

    涵盖有关JavaScript闭包的一些理论(足以提高生产力并了解我们在写什么)
  • look into examples in more detail

    更详细地研究示例

By the end of the article we will be able to understand what is a closure and how we can benefit from it in the JavaScript world.

到本文结尾,我们将能够了解什么是闭包以及如何在JavaScript世界中从中受益。

JavaScript中的闭包是什么 (What’s a closure in JavaScript)

In simple terms, closure gives us access to an outer function scope from an inner function. The closure in JavaScript has three scope chains:

简单来说,闭包使我们可以从内部函数访问外部函数范围。 JavaScript中的闭包具有三个作用域链:

  • it has access to its own scope (between it’s own curly brackets)

    它可以访问自己的范围(在自己的大括号之间)
  • it has access to the outer function scope

    它可以访问外部功能范围
  • it has access to the global scope

    它可以进入全球范围

In JavaScript, closures are created every time a function is created, at function creation time.

在JavaScript中, 每次创建函数时都会在函数创建时创建闭包。

一个简单的例子开始 (A simple example to begin with)

function outer() {

const b = 50;

function inner() {
const a = 100;
console.log(`a is ${a} and b is ${b}, the sum is ${a+b}`);
} return inner;
}// first invocation of outer
const fnFirst = outer();// second invocation of outer
const fnSecond = outer();// what's inside?
// note console.dir() and not console.log() commandconsole.dir(fnFirst);
console.dir(fnSecond);

To understand what is closure let’s walk through this example.

要了解什么是闭包,让我们来看一下这个示例。

第一次调用函数external() (Function outer() invoked for the first time)

  1. We create variable b. The scope of variable b is limited to the outer function. The value is set to 100. To keep things more readable, I’ve initialised it with const. This means, that the value cannot be reassigned.

    我们创建变量b 。 变量b的范围限于outer函数。 该值设置为100 。 为了使内容更具可读性,我已使用const对其进行了初始化。 这意味着不能重新分配该值。

  2. Then we declare function inner — nothing is executed.

    然后,我们将函数声明为inner -不执行任何操作。

  3. Next, we find return inner. It turns out that inner is a function and as such we return the function body.

    接下来,我们找到return inner 。 事实证明, inner是一个function ,因此我们返回了函数主体。

    Please note that the statement

    请注意,声明

    return inner does not execute function inner. Function is executed only when followed by () i.e. inner().

    return inner 不执行函数inner 。 仅在后跟()inner()时才执行函数。

  4. The content returned by return inner is stored into fnFirst variable.

    return inner返回的内容存储在fnFirst变量中。

    In this case, it’s the body of function

    在这种情况下,它是功能的主体

    inner.

    inner

  5. Function outer() finishes execution.

    函数outer()完成执行。

    All variables within the scope of

    范围内的所有变量

    outer() no longer exist.

    outer()不再存在。

    This is very important to understand, so I will repeat that. :)

    了解这一点非常重要,因此我将重复一遍。 :)

Once a function completes its execution, any variables defined inside the function scope no longer exist.

一旦函数完成执行,在函数范围内定义的任何变量将不复存在。

This means that our variable b declared inside outer function, exists only when outer function is being executed.

这意味着我们在outer函数内部声明的变量b仅在执行outer函数时存在。

When we execute the function for the second time, the variables of the function are created again (from scratch).

当我们第二次执行该函数时,将再次(从头开始)创建该函数的变量。

Let’s track down what happens when we invoke function outer for the second time (and store it into different variable).

让我们追踪一下第二次调用outer函数(并将其存储到其他变量中)时发生的情况。

第二次调用函数external() (Function outer() invoked for the second time)

  1. We create variable b. The scope of variable b is limited to the outer function. The value is set to 100.

    我们创建变量b 。 变量b的范围限于outer函数。 该值设置为100

  2. Then we declare function inner so nothing is executed.

    然后,我们将函数声明为inner因此不执行任何操作。

  3. Similarly, return inner return the body of inner — remember the function is not called.

    同样, return inner收益身体inner -记函数没有被调用。

  4. The contents returned by the return statement are stored in fnSecond.

    return语句返回的内容存储在fnSecond

  5. Function outer() finishes execution.

    函数outer()完成执行。

    All variables within the scope of

    范围内的所有变量

    outer() no longer exist.

    outer()不再存在。

Here comes the important bit (once again but it’s worth repeating).

重要的地方到了(再次,但是值得重复)。

When the outer() function is invoked for the second time, the variable b is created from fresh. The variable b cease to exist once outer finishes executing.

当第二次调用external outer()函数时,将从新创建变量b 。 一旦outer完成执行,变量b不再存在。

使开发人员感到困惑的部分 (The part that is confusing the devs)

So far it looks rather clear.

到目前为止,看起来还很清楚。

We have returned our function into two different variables fnFirst and fnSecond. These two variables are in fact functions, which we can verify with help of typeof. The variables fnFirstand fnSecondboth have the function body of inner

我们已将函数返回到两个不同的变量fnFirstfnSecond 。 这两个变量实际上是函数,我们可以在typeof帮助下进行验证。 变量fnFirstfnSecond都具有inner函数体

console.log(fnFirst);// outputƒ inner() {
const a = 100;
console.log(`a is ${a} and b is ${b}, the sum is ${a + b}`);
}

Here comes the tricky part

棘手的部分到了

The console.logwants to print variable b.

console.log要打印变量b

How we will be able to access the variable b which was declared in the scope of function outer ?

我们将如何访问在函数outer范围内声明的变量b

An example to help us:

一个可以帮助我们的例子:

// continuedconst fnFirst = outer();
const fnSecond = outer();// for the first time
// output -> a is 100 and b is 50, the sum is 150
fnFirst();// for the second time
// output -> a is 100 and b is 50, the sum is 150
fnFirst();// for the third time
// output -> a is 100 and b is 50, the sum is 150
fnFirst();// for the first time
// output -> a is 100 and b is 50, the sum is 150
fnSecond();

The following happens on the invocation of fnFirst().

调用fnFirst()时发生以下情况。

  1. Variable a is created, it’s value is set to 100.

    创建变量a ,其值设置为100

  2. In the second line, the function tries to add a + b.

    在第二行中,该函数尝试添加a + b

    Variable

    变量

    ahas just been created, that part is clear.

    a刚刚创建,那部分很清楚。

    But there is no

    但是没有

    b in the function body.

    b在功能主体中。

    We’ve said earlier, that the

    我们之前说过,

    b variable exists only when function outer is executed.

    b变量仅在执行outer函数时存在。

We still don’t know how does inner function knows about the variable b.

我们仍然不知道inner函数如何知道变量b

营救结束 (Closures to the rescue)

If we would do console.dir(fnFirst) , we would see something similar in the console:

如果我们执行console.dir(fnFirst) ,我们将在控制台中看到类似的内容:

We can see that there is a Closure that has variable b = 50

我们可以看到一个闭包具有变量b = 50

That’s our answer!

那就是我们的答案!

The inner function has preserved the value of variable b and continues to closure it.

inner函数保留了变量b的值并继续对其进行封闭。

The inner function preserves the scope chain of the enclosing function at the time the enclosing function was executed. In simple terms, this means that inner function can access outer function variables with help from closure.

inner函数在执行封闭函数时保留了封闭函数的作用域链。 简单来说,这意味着inner函数可以在闭包的帮助下访问outer函数变量。

As we have said in the beginning. The inner function has access to three scope chains:

正如我们在一开始所说的。 内部函数可以访问三个作用域链:

  • the inner scope i.e. a

    内范围即a

  • the outer scope i.e. b

    外部范围即b

  • the global scope

    全球范围

In JavaScript, closures are created every time a function is created, at function creation time.

在JavaScript中,每次创建函数时都会在函数创建时创建闭包

更困难的例子 (More difficult example)

In the job interview you will be probably be given a code snippet similar to that one:

在工作面试中,您可能会收到与该代码段相似的代码段:

Then the interviewer would probably ask you the following questions:

然后,面试官可能会问您以下问题:

  • tell me what this snippet is? (we already know it’s closure)

    告诉我这个片段是什么? (我们已经知道它是关闭的)
  • walk me through what’s happening? (most important part)

    引导我了解发生了什么事? (最重要的部分)
  • what will be the output in the console?

    控制台中的输出是什么?

To answer that questions, let’s walk through what happens when we invoke fnFirst for the first time (let’s remember that we are looking at inner function as this is what has been returned):

为了回答这些问题,让我们fnFirst一下第一次调用fnFirst时会发生什么(请记住,我们正在查看inner函数,因为这是返回的结果):

fnFirst首次调用 (fnFirst invoked for the first time)

  1. Variable c is created and initialised as 20.

    创建变量c并将其初始化为20

  2. Message is logged into the console with a,b,c variables.

    消息将使用a,b,c变量登录到控制台。

    We already know that variables

    我们已经知道变量

    a and b are available and come from the closure.

    ab都可用,并且来自于闭包。

    We can think of it like

    我们可以这样想

    a(first_time) and b(first_time).

    a(first_time)b(first_time)

    Hence

    因此

    a = 10 and b = 100.

    a = 10b = 100

  3. The variable b, coming from the closure and c variable coming from inner function are incremented.

    来自闭包的变量b和来自inner函数的c变量递增。

  4. When the function fnFirst completes execution, the variables inside it (c ) cease to exist.

    当函数fnFirst完成执行时,函数( c )中的变量将不复存在。

    However, the value

    但是,价值

    b was preserved to the closure and as such is preserved to the next function call.

    b 保留在闭包中 ,因此保留在下一个函数调用中

在第二,第三和…时间调用fnFirst() (fnFirst() invoked for the second, third, and … time)

It’s similar as the first invocation, the only difference is step 2 — the value of b variable is already incremented.

它与第一次调用类似,唯一的区别是步骤2 – b变量的值已经增加。

  1. The variable c is created and initiated as 20

    创建变量c并将其初始化为20

  2. The variable b, coming from the closure, is incremented by 1 hence it’s value is 101. In next function call it will be 102, then 103and so on.

    来自闭包的变量b增加1因此其值为101 。 在下一个函数调用中,它将是102 ,然后是103 ,依此类推。

  3. b variable, coming from the closure and c variable coming from inner function are yet again incremented.

    来自闭包的b变量和来自inner函数的c变量再次递增。

  4. When the function fnFirst completes execution, the variables inside it ( i.e. c ) cease to exist. However, the value b was preserved to the closure and as such is preserved to the next function call.

    当函数fnFirst完成执行时,其中的变量(即c )将不复存在。 但是,值b保留给闭包,因此保留给下一个函数调用。

You can also use closures for a pattern called partial application but that is a story for another article.

您也可以将闭包用于称为部分应用程序的模式,但这是另一篇文章的故事。

摘要 (Summary)

Closures are initially difficult to understand especially when introduced with advanced jargon definitions.

闭包最初很难理解,尤其是在引入高级术语定义时。

If that’s the case, we can try to ignore the jargon initially, go through some examples, understand them, and then come back to the jargon.

如果是这种情况,我们可以尝试先忽略术语,通过一些示例,理解它们,然后再回到术语。

With a bit of practice you will probably come to realise that closure is in fact intuitive, powerful tool for us.

通过一些实践,您可能会发现封闭实际上对我们来说是直观,功能强大的工具。

PS

聚苯乙烯

There is no escape from closure s— you still have to understand it on a job interview (or at an exam).

结束考试无可避免,您仍然必须在求职面试(或考试)中了解它。

翻译自: https://medium.com/@tymekluczko/closures-in-javascript-in-simple-terms-and-real-life-examples-b997c4acdc4b

闭包的示例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值