JavaScript闭包的奇怪行为

huangapple go评论74阅读模式
英文:

Javasript closure stange behaviour

问题

嗨,我正在学习JavaScript闭包,这段代码对我来说表现得很奇怪:

function Unique_id2() {
    let counter = 0;
    function f() { return counter++; };
    return f();
}

console.log("UID2");
let f = Unique_id2;
console.log(typeof f);
console.log(f());
console.log(f());
console.log(f());
console.log(f());
console.log(f());

结果是:

UID2
functions.js:65 function
functions.js:66 0
functions.js:67 0
functions.js:68 0
functions.js:69 0
functions.js:70 0

这对我来说很奇怪,因为计数器应该每次递增...

你能解释一下出了什么问题吗?

编辑

function Unique_id2() {
    let counter = 0;
    function f() { return counter++; };
    return f;
}

console.log("UID2");
let f = Unique_id2;
console.log(typeof f);
console.log(Unique_id2()());
console.log(Unique_id2()());
console.log(Unique_id2()());
console.log(Unique_id2()());
console.log(Unique_id2()());

产生了相同的结果。

英文:

emphasized textHi I'm learning Javascripts closures and tjis code beahves funny to me:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function Unique_id2() {
    let counter = 0;
    function f() { return counter++; };
    return f();
}

console.log(&quot;UID2&quot;);
let f = Unique_id2;
console.log(typeof f);
console.log(f());
console.log(f());
console.log(f());
console.log(f());
console.log(f());

<!-- end snippet -->

the result is:

UID2
functions.js:65 function
functions.js:66 0
functions.js:67 0
functions.js:68 0
functions.js:69 0
functions.js:70 0

which is strangge to me since the counter souhld be incrementsd each time ...

can you explain what's wrong

EDIT

function Unique_id2() {
        let counter = 0;
        function f() { return counter++; };
        return f;
    }

    console.log(&quot;UID2&quot;);
    let f = Unique_id2;
    console.log(typeof f);
    console.log(Unique_id2()());
    console.log(Unique_id2()());
    console.log(Unique_id2()());
    console.log(Unique_id2()());
    console.log(Unique_id2()());

yields the same result

答案1

得分: 2

你没有返回闭包,而是每次调用Unique_id2()时都直接调用它。每次这样做时,它都会将计数器重置为0并返回该值。

要获得递增的计数器,你必须返回闭包,而不是调用它的结果。然后,你应该重复调用闭包以获得每个递增的值。

因此,在下面的代码中,你调用Unique_id2()并将其赋值给变量,如ff2。然后,当你调用f()时,你会得到递增的计数器值。

function Unique_id2() {
    let counter = 0;
    function f() { return counter++; };
    return f;
}

console.log("UID");
let f = Unique_id2();
console.log(typeof f);

console.log(f());
console.log(f());
console.log(f());
console.log(f());
console.log(f());

console.log("UID2");
let f2 = Unique_id2();
console.log(typeof f2);
console.log(f2());
console.log(f2());
英文:

You're not returning the closure, you're just calling it each time you call Unique_id2(). And each time you do that, it resets the counter to 0 and returns that.

To get an incrementing counter, you have to return the closure, not the result of calling it. Then you should call that closure repeatedly to get each incremented value.

So in the code below, you call Unique_id2() and assign that to a variable like f or f2. Then when you call f() you get the incrementing counter values.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function Unique_id2() {
    let counter = 0;
    function f() { return counter++; };
    return f;
}

console.log(&quot;UID&quot;);
let f = Unique_id2();
console.log(typeof f);

console.log(f());
console.log(f());
console.log(f());
console.log(f());
console.log(f());

console.log(&quot;UID2&quot;);
let f2 = Unique_id2();
console.log(typeof f2);
console.log(f2());
console.log(f2());

<!-- end snippet -->

答案2

得分: 0

即使使用不同的名称和引用,每次都在调用Unique_id2

每次调用它时,Unique_id2函数都会将变量counter初始化为0。

为了实现你想要的效果,你需要将counter的初始化移到Unique_id2的作用域之外,像这样:

let counter = 0;

function Unique_id2() {    
    function f() { return counter++; };
    return f;
}

console.log("UID");
let f = Unique_id2();
console.log(typeof f);

console.log(f());
console.log(f());
console.log(f());
console.log(f());

这样,counter变量只会被初始化一次,并且由于闭包的存在,Unique_id2函数可以访问它。

英文:

Even with different names and references, you're calling Unique_id2 every time.

And every time it is invoked, the Unique_id2 function initialises the variable counter to 0.

To achieve what you are trying to do, you need to move the initialisation of counter out of the Unique_id2 scope, like this:

let counter = 0;

function Unique_id2() {    
    function f() { return counter++; };
    return f;
}

console.log(&quot;UID&quot;);
let f = Unique_id2();
console.log(typeof f);

console.log(f());
console.log(f());
console.log(f());
console.log(f());

This way the counter variable is initialised only once, and thanks to the closure, the Unique_id2 has access to it.

huangapple
  • 本文由 发表于 2023年8月9日 02:56:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76862469.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定