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

Categories

A friend of mine and I are currently discussing what is a closure in JS and what isn't.

(我的一个朋友和我正在讨论什么是JS的封闭,什么不是。)

We just want to make sure we really understand it correctly.

(我们只是想确保我们真正理解它。)

Let's take this example.

(我们来看看这个例子吧。)

We have a counting loop and want to print the counter variable on the console delayed.

(我们有一个计数循环,并希望在控制台上打印计数器变量延迟。)

Therefore we use setTimeout and closures to capture the value of the counter variable to make sure that it will not print N times the value N.

(因此,我们使用setTimeout闭包来捕获计数器变量的值,以确保它不会打印N倍N值。)

The wrong solution without closures or anything near to closures would be:

(错误的解决方案,而闭合或接近闭合 ,以将任何东西:)

for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}

which will of course print 10 times the value of i after the loop, namely 10.

(这将当然打印的10倍的值i在循环后,也就是10。)

So his attempt was:

(所以他的尝试是:)

for(var i = 0; i < 10; i++) {
    (function(){
        var i2 = i;
        setTimeout(function(){
            console.log(i2);
        }, 1000)
    })();
}

printing 0 to 9 as expected.

(按预期打印0到9。)

I told him that he isn't using a closure to capture i , but he insists that he is.

(我告诉他,他并没有使用封闭来捕获i ,但他坚持认为他是。)

I proved that he doesn't use closures by putting the for loop body within another setTimeout (passing his anonymous function to setTimeout ), printing 10 times 10 again.

(我通过将for循环体放在另一个setTimeout (将他的匿名函数传递给setTimeout ),再次打印10次10??来证明他没有使用闭包 。)

The same applies if I store his function in a var and execute it after the loop, also printing 10 times 10. So my argument is that he doesn't really capture the value of i , making his version not a closure.

(如果我将他的函数存储在var并在循环之后执行它同样适用,也打印10次10??.所以我的论点是他并没有真正捕获 i的值 ,使他的版本不是一个闭包。)

My attempt was:

(我的尝试是:)

for(var i = 0; i < 10; i++) {
    setTimeout((function(i2){
        return function() {
            console.log(i2);
        }
    })(i), 1000);
}

So I capture i (named i2 within the closure), but now I return another function and pass this around.

(所以我捕获了i (在闭包中命名为i2 ),但现在我返回另一个函数并传递它。)

In my case, the function passed to setTimeout really captures i .

(在我的例子中,传递给setTimeout的函数实际上捕获了i)

Now who is using closures and who isn't?

(现在谁在使用闭包,谁不是?)

Note that both solutions print 0 to 9 on the console delayed, so they solve the original problem, but we want to understand which of those two solutions uses closures to accomplish this.

(请注意,两个解决方案在控制台上打印0到9都会延迟,因此它们解决了原始问题,但我们想要了解这两个解决方案中的哪一个使用闭包来实现此目的。)

  ask by leemes translate from so

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

1 Answer

Editor's Note: All functions in JavaScript are closures as explained in this post .

(编者按:在JavaScript中所有的功能都关闭在这个解释 。)

However we are only interested in identifying a subset of these functions which are interesting from a theoretical point of view.

(不过我们只是在识别这些功能,这是一个子集,有兴趣的有趣从理论角度。)

Henceforth any reference to the word closure will refer to this subset of functions unless otherwise stated.

(此后,除非另有说明,否则对闭包一词的任何引用都将指代该功能子集。)

A simple explanation for closures:

(闭包的简单解释:)

  1. Take a function.

    (拿一个功能。)

    Let's call it F.

    (我们称之为F.)

  2. List all the variables of F.

    (列出F的所有变量)

  3. The variables may be of two types:

    (变量可以有两种类型:)

    1. Local variables (bound variables)

      (局部变量(绑定变量))

    2. Non-local variables (free variables)

      (非局部变量(自由变量))

  4. If F has no free variables then it cannot be a closure.

    (如果F没有自由变量那么它就不能成为闭包。)

  5. If F has any free variables (which are defined in a parent scope of F) then:

    (如果F有任何自由变量(在F 父范围中定义),则:)

    1. There must be only one parent scope of F to which a free variable is bound.

      (必须有其中自由变量所键合的F只有一个父范围。)

    2. If F is referenced from outside that parent scope, then it becomes a closure for that free variable.

      (如果F从父范围之外引用 ,则成为自由变量的封闭件。)

    3. That free variable is called an upvalue of the closure F.

      (自由变量称为闭包F的upvalue。)

Now let's use this to figure out who uses closures and who doesn't (for the sake of explanation I have named the functions):

(现在让我们用它来确定谁使用闭包,谁不使用闭包(为了解释我已经命名了函数):)

Case 1: Your Friend's Program

(案例1:您朋友的计划)

for (var i = 0; i < 10; i++) {
    (function f() {
        var i2 = i;
        setTimeout(function g() {
            console.log(i2);
        }, 1000);
    })();
}

In the above program there are two functions: f and g .

(在上面的程序中有两个函数: fg 。)

Let's see if they are closures:

(让我们看看它们是否是闭包:)

For f :

(对于f :)

  1. List the variables:

    (列出变量:)

    1. i2 is a local variable.

      (i2是一个局部变量。)

    2. i is a free variable.

      (i是一个自由变量。)

    3. setTimeout is a free variable.

      (setTimeout是一个自由变量。)

    4. g is a local variable.

      (g局部变量。)

    5. console is a free variable.

      (console是一个自由变量。)

  2. Find the parent scope to which each free variable is bound:

    (找到每个自由变量绑定到的父作用域:)

    1. i is bound to the global scope.

      (i 全球范围的约束 。)

    2. setTimeout is bound to the global scope.

      (setTimeout 绑定到全局范围。)

    3. console is bound to the global scope.

      (console 绑定到全局范围。)

  3. In which scope is the function referenced ?

    (引用的函数在哪个范围内?)

    The global scope .

    (全球范围 。)

    1. Hence i is not closed over by f .

      (因此i没有被f 关闭 。)

    2. Hence setTimeout is not closed over by f .

      (因此, setTimeout不会被f 关闭 。)

    3. Hence console is not closed over by f .

      (因此, console不会被f 关闭 。)

Thus the function f is not a closure.

(因此,函数f不是闭包。)

For g :

(对于g :)

  1. List the variables:

    (列出变量:)

    1. console is a free variable.

      (console是一个自由变量。)

    2. i2 is a free variable.

      (i2是一个自由变量。)

  2. Find the parent scope to which each free variable is bound:

    (找到每个自由变量绑定到的父作用域:)

    1. console is bound to the global scope.

      (console 绑定到全局范围。)

    2. i2 is bound to the scope of f .

      (i2 f的范围约束 。)

  3. In which scope is the function referenced ?

    (引用的函数在哪个范围内?)

    The scope of setTimeout .

    (setTimeout范围 。)

    1. Hence console is not closed over by g .

      (因此console没有被g 关闭 。)

    2. Hence i2 is closed over by g .

      (因此i2g 关闭 。)

Thus the function g is a closure for the free variable i2 (which is an upvalue for g ) when it's referenced from within setTimeout .

(因此, setTimeout 引用 ,函数g是自由变量i2的闭包(对于g是一个up值)。)

Bad for you: Your friend is using a closure.

(对你不好:你的朋友正在使用关闭。)

The inner function is a closure.

(内部函数是一个闭包。)

Case 2: Your Program

(案例2:您的计划)

for (var i = 0; i < 10; i++) {
    setTimeout((function f(i2) {
        return function g() {
            console.log(i2);
        };
    })(i), 1000);
}

In the above program there are two functions: f and g .

(在上面的程序中有两个函数: fg 。)

Let's see if they are closures:

(让我们看看它们是否是闭包:)

For f :

(对于f :)

  1. List the variables:

    (列出变量:)

    1. i2 is a local variable.

      (i2是一个局部变量。)

    2. g is a local variable.

      (g局部变量。)

    3. console is a free variable.

      (console是一个自由变量。)

  2. Find the parent scope to which each free variable is bound:

    (找到每个自由变量绑定到的父作用域:)

    1. console is bound to the global scope.

      (console 绑定到全局范围。)

  3. In which scope is the function referenced ?

    (引用的函数在哪个范围内?)

    The global scope .

    (全球范围 。)

    1. Hence console is not closed over by f .

      (因此, console不会被f 关闭 。)

Thus the function f is not a closure.

(因此,函数f不是闭包。)

For g :

(对于g :)

  1. List the variables:

    (列出变量:)

    1. console is a free variable.

      (console是一个自由变量。)

    2. i2 is a free variable.

      (i2是一个自由变量。)

  2. Find the parent scope to which each free variable is bound:

    (找到每个自由变量绑定到的父作用域:)

    1. console is bound to the global scope.

      (console 绑定到全局范围。)

    2. i2 is bound to the scope of f .

      (i2 f的范围约束 。)

  3. In which scope is the function referenced ?

    (引用的函数在哪个范围内?)

    The scope of setTimeout .

    (setTimeout范围 。)

    1. Hence console is not closed over by g .

      (因此console没有被g 关闭 。)

    2. Hence i2 is closed over by g .

      (因此i2g 关闭 。)

Thus the function g is a closure for the free variable i2 (which is an upvalue for g ) when it's referenced from within setTimeout .

(因此, setTimeout 引用 ,函数g是自由变量i2的闭包(对于g是一个up值)。)

Good for you: You are using a closure.

(


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...