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

如何结合递归与辅助函数理解作用域/闭包?附二叉树示例解析

递归辅助函数中作用域/闭包的核心:值类型 vs 引用类型

我来帮你彻底理清这里的关键差异——你碰到的问题本质是JavaScript里值类型和引用类型的传递规则不同,这直接决定了辅助函数能不能修改父作用域的变量。

先拆解你的两个示例

示例1:为什么maxDepth始终停留在1?

先看你写的错误版本代码:

var maxDepth = function(root) {
  if (root === null) return 0;
  var maxDepth = 1;
  maxDepthHelper(root, 1, maxDepth);
  return maxDepth;
};
function maxDepthHelper(tree, depth, maxDepth) {
  if (tree.left === null && tree.right === null) {
    maxDepth = depth > maxDepth ? depth : maxDepth;
    return;
  }
  if (tree.left) {
    maxDepthHelper(tree.left, depth + 1, maxDepth);
  }
  if (tree.right) {
    maxDepthHelper(tree.right, depth + 1, maxDepth);
  }
}

这里的maxDepth是一个值类型(number),当你把它传给maxDepthHelper时,JS传递的是它的副本。也就是说,辅助函数里的maxDepth和父函数里的maxDepth是完全独立的两个变量——你在辅助函数里修改这个副本,根本碰不到父作用域里的那个变量。再加上错误版辅助函数没有返回修改后的副本,父函数里的maxDepth自然一直是初始的1。

而正确版本之所以能生效,是因为每次调用辅助函数时,都把返回的新值重新赋值给了父作用域的maxDepth,相当于把副本的结果“带”回了父作用域:

// 正确版里的关键步骤
maxDepth = maxDepthHelper(tree.left, depth + 1, maxDepth);

示例2:为什么数组能被辅助函数修改?

再看这个二叉搜索树的示例代码:

var kthSmallest = function(root, k) {
  let smallestArr = [];
  kthSmallestHelper(root, k, smallestArr);
  return smallestArr.pop()
};
function kthSmallestHelper(bst, k, array) {
  if (bst === null) return;
  kthSmallestHelper(bst.left, k, array);
  if (array.length === k) return;
  array.push(bst.val);
  kthSmallestHelper(bst.right, k, array);
}

这里的smallestArr是引用类型(Array),当你把它传给辅助函数时,JS传递的是这个数组在内存中的引用地址。也就是说,辅助函数里的array和父函数里的smallestArr指向的是同一个内存对象。所以你在辅助函数里做array.push(),本质是修改了这个共享的对象,父作用域里的数组自然也会跟着变化。

你忽略的核心规则

  • 值类型(number、string、boolean、null、undefined、symbol):函数参数传递的是值的副本,函数内部修改参数不会影响外部变量,必须通过返回值把修改后的结果传递回去。
  • 引用类型(object、array、function等):函数参数传递的是引用地址,函数内部对对象的修改会直接反映到外部,因为它们指向同一个内存对象。
  • 闭包在这里的作用是让辅助函数能访问父作用域的变量,但能不能修改还要看变量的类型和传递规则——闭包给了访问权,但修改权由值/引用传递的规则决定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 12:22:46