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
相关产品推荐
相关产品推荐

