You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript闭包异常行为解惑:为何计数器无法递增?

JavaScript闭包问题:为什么counter始终返回0?

我正在学习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()());

运行结果仍每次返回0,我认为counter应每次递增,请问问题出在哪里?


问题分析

第一段代码的问题

Unique_id2函数返回的是f()的执行结果,也就是调用f后得到的counter初始值0。每次调用f()(或者Unique_id2()),都会重新创建一个全新的counter变量,执行f()返回0后,函数执行上下文销毁,counter也随之被回收,所以每次调用都是0。

第二段代码的问题

虽然Unique_id2现在返回的是函数f本身,但你每次调用Unique_id2()(),相当于每次都重新执行一遍Unique_id2()。每执行一次Unique_id2(),都会创建一个新的counter变量(初始值0),返回的f是绑定这个新counter的闭包,调用一次f就返回0,之后这个上下文被销毁。下次调用Unique_id2()()时,又是一个全新的counter,自然还是返回0。

正确实现方式

要让counter持续递增,需要只创建一次Unique_id2的执行上下文,让闭包持续引用同一个counter。只需要把Unique_id2()的执行结果(也就是闭包函数f)赋值给一个变量,之后每次调用这个变量即可:

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

console.log("UID2");
// 仅执行一次Unique_id2,得到绑定了同一个counter的闭包函数
let getUniqueId = Unique_id2();
console.log(typeof getUniqueId);
console.log(getUniqueId()); // 0
console.log(getUniqueId()); // 1
console.log(getUniqueId()); // 2
console.log(getUniqueId()); // 3
console.log(getUniqueId()); // 4

这里getUniqueId保存的是Unique_id2()返回的f函数,这个闭包会持续引用Unique_id2执行时创建的counter变量,每次调用getUniqueId()都会修改同一个counter,因此会实现递增效果。


内容的提问来源于stack exchange,提问作者Luca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 18:33:38