请结合map方法签名与闭包,分步解释这段JS代码的运行原理
拆解这段带闭包的map累加代码运行逻辑
首先明确map方法的签名:
array.map(function(currentValue, index, arr), thisValue)
map会遍历数组的每一个元素,依次调用传入的回调函数,每次调用时会自动传入三个参数:当前遍历到的元素currentValue、元素的索引index、原数组arr,最终返回一个由所有回调返回值组成的新数组。
先看懂代码的写法
你给出的代码里,map的参数是一个逗号表达式:(acc = 0 , num => acc += num)。逗号运算符的规则是依次执行所有操作数,返回最后一个操作数的值,所以这里实际发生的是:
- 先执行
acc = 0,给变量acc赋值为0; - 把后面的箭头函数
num => acc += num作为回调函数传给map。
而这个箭头函数不会创建自己的词法环境,它会沿用定义时所在的上下文,所以acc会被所有回调调用共享,这就是闭包的作用——函数能访问并保留定义时环境里的变量。
分步可视化运行过程
初始化:
- 变量
acc被赋值为0; map拿到的回调函数是num => acc += num。
开始遍历数组[1,2,3,4,5]:
第一次遍历(元素1):
- 回调接收
currentValue为1; - 执行
acc += 1→0 + 1 = 1; acc更新为1;- 回调返回1,新数组第一个元素是
1。
- 回调接收
第二次遍历(元素2):
- 回调接收
currentValue为2; - 执行
acc += 2→1 + 2 = 3; acc更新为3;- 回调返回3,新数组第二个元素是
3。
- 回调接收
第三次遍历(元素3):
- 回调接收
currentValue为3; - 执行
acc += 3→3 + 3 = 6; acc更新为6;- 回调返回6,新数组第三个元素是
6。
- 回调接收
第四次遍历(元素4):
- 回调接收
currentValue为4; - 执行
acc += 4→6 + 4 = 10; acc更新为10;- 回调返回10,新数组第四个元素是
10。
- 回调接收
第五次遍历(元素5):
- 回调接收
currentValue为5; - 执行
acc += 5→10 + 5 = 15; acc更新为15;- 回调返回15,新数组第五个元素是
15。
- 回调接收
最终map返回新数组[1,3,6,10,15],被console.log输出。
关于闭包的补充
这里的acc是闭包变量,意味着只要这个回调函数还能被访问到,acc的值就会一直保留。比如后续再用这个回调做map:
const cb = (acc = 0, num => acc += num); console.log([1,2].map(cb)); // 输出 [1,3] console.log([3].map(cb)); // 输出 [6](因为acc已经是3,加3变成6)
内容的提问来源于stack exchange,提问作者iamworldian
相关产品推荐
相关产品推荐

