JavaScript闭包与作用域疑问:为何humansMoney调用时未重置为100
理解闭包与作用域:为什么humansMoney不会重置?
首先我得把你提到的示例代码还原出来(闭包的经典例子基本都是这个路数),应该是类似这样:
function human() { // 外部函数的变量 let humansMoney = 100; // 返回一个内部函数 return function() { humansMoney--; console.log(humansMoney); }; } // 这里调用了一次human(),得到它返回的内部函数,赋值给carl const carl = human(); // 调用carl(),执行的是内部函数 carl(); // 输出99 carl(); // 输出98
你的困惑点在于:为什么每次调用carl()的时候,humansMoney不会重新变成100? 核心原因其实是:carl()根本没有调用human()——carl本身就是human()执行一次后返回的那个内部函数!
拆解整个过程:
当你执行
const carl = human();这一行时,human()函数被调用了一次:- 创建了
humansMoney变量并赋值为100; - 返回了内部的匿名函数;
- 此时
human()的执行上下文看似结束,但因为返回的内部函数引用了humansMoney,闭包会把这个变量所在的作用域“保留”下来,相当于给内部函数留了一把能访问这个变量的“钥匙”。
- 创建了
之后每次调用
carl(),都是直接执行那个被返回的内部函数:- 它不会重新触发
human()的执行,所以humansMoney = 100这行代码不会再运行; - 它通过闭包访问的是之前
human()执行时创建的那个humansMoney变量,所以每次调用只会让同一个变量递减。
- 它不会重新触发
举个生活化的例子:
把human()想象成一个制作存钱罐的机器:
- 你按下机器按钮(调用
human()),机器做了一个装有100块钱的存钱罐,还给你一把能打开这个存钱罐的钥匙(返回内部函数); - 这把钥匙就是
carl,你每次用钥匙开门(调用carl()),都是从同一个存钱罐里拿钱,而不是让机器重新做一个新的存钱罐; - 如果想要一个新的、初始100块的存钱罐,你得再按一次机器按钮(再调用一次
human()),比如const alice = human();,这时候alice对应的就是另一个独立的存钱罐了。
验证你的假设:
如果真的想让每次调用都重置为100,那你需要每次都调用human(),比如:
// 每次都重新调用human(),得到新的内部函数,自然humansMoney会重置 human()(); // 99 human()(); // 99
这样每次执行human()都会创建一个新的humansMoney变量,所以每次的结果都是99,而不是递减。
内容的提问来源于stack exchange,提问作者josh_c
相关产品推荐
相关产品推荐

