JavaScript递归函数按值传递问题及零计数实现疑问
JavaScript的参数传递:只有按值传递,没有按引用传递
核心结论
JavaScript仅支持按值传递,不存在所谓的“按引用传递”。很多人混淆的“引用传递”其实是对引用类型的按值传递——传递的是引用的副本,而非原始引用本身。
结合你的代码分析
你遇到的问题,本质是对JS参数传递规则的误解:
- 第二个代码里,递归调用
countZeroes(parseInt(num / 10))时没有传递更新后的count参数,这是直接导致结果错误的第一个问题; - 即使你传递了count,因为count是Number类型(基本类型),传递的是值的副本——函数内部修改的是这个副本,不会影响外部的count变量。
正确的递归实现方式
方式1:利用递归返回值累加(推荐,无副作用)
不需要依赖外部变量或引用类型,直接通过递归的返回值计算结果:
const number = 3004; const countZeroes = function(num) { // 递归终止条件:num为0时返回0 if (num === 0) { return 0; } // 计算当前位是否为0,加上递归调用的结果 const current = num % 10 === 0 ? 1 : 0; return current + countZeroes(Math.floor(num / 10)); } const result = countZeroes(number); console.log('the result ', result); // 输出2
方式2:用引用类型传递计数(不推荐,有副作用)
如果一定要通过传递的方式维护计数,可以把count放在一个对象(引用类型)里,传递对象的引用副本,修改对象的属性会影响外部:
const number = 3004; const countZeroes = function(num, counter) { if (num === 0) { return; } if (num % 10 === 0) { counter.value += 1; } // 递归调用时必须传递counter参数 countZeroes(Math.floor(num / 10), counter); } const counter = { value: 0 }; countZeroes(number, counter); console.log('the result ', counter.value); // 输出2
再明确JS的参数传递规则
- 对于基本类型(Number、String、Boolean、Null、Undefined、Symbol、BigInt):传递的是值的副本,函数内部修改参数不会影响外部变量;
- 对于引用类型(Object、Array、Function等):传递的是引用的副本——你可以通过这个副本修改引用指向的对象内容,但不能修改原始引用本身(比如把参数重新赋值为另一个对象,不会影响外部的引用)。
内容的提问来源于stack exchange,提问作者Ashy Ashcsi
相关产品推荐
相关产品推荐

