JS求二叉树直径时 const/var/let声明与否变量结果差异问题
异常结果产生原因
不给left、right变量加const/let/var声明关键字时,会触发JavaScript的隐式全局变量规则,直接把递归逻辑里本该独立的临时变量变成全局共享变量,结果必然出错,具体机制:
- JavaScript中,未经过声明关键字定义就直接赋值的变量,不会被识别为当前函数作用域的局部变量。引擎会顺着作用域链向上查找同名变量,一直找到全局作用域,如果全局范围也没有对应变量,就会直接在全局对象上挂载这个变量,所有代码位置都能读写它。
- 你实现的
dfs是深度优先遍历的递归函数,运行时会同时叠着多层调用栈:每一层递归处理对应树节点时,都会重写全局的left、right值,深层递归算出来的返回值会直接覆盖浅层递归暂存的左右子树计算结果。原本应该每一层函数调用独立保存的左右子树返回值,变成了全局共用的变量,导致当前节点算直径、算深度的时候拿到的根本不是自己左右子树的结果,输出自然不对。 - 加上
const声明之后,left、right是每次dfs调用独立的块级局部变量,不同递归层级的同名变量完全互不干扰,每一层都能正确拿到自己左右子树的递归返回值做计算,结果就正常了。
可正常运行的正确声明版本代码如下:
var diameterOfBinaryTree = function(root) { const result = dfs(root, 0); return result[1]; }; const dfs = (node, diameter) => { if(!node) return [0, 0]; const left = dfs(node.left, diameter); const right = dfs(node.right, diameter); let oldDiameter = Math.max(left[1], right[1], diameter); let newDiameter = Math.max(oldDiameter, left[0] + right[0]); let depth = Math.max(left[0], right[0]) + 1; return [depth, newDiameter]; }
补充提示:如果开启严格模式(代码开头加'use strict'),给未声明的变量赋值会直接抛出ReferenceError,不会静默创建全局变量,可以提前规避这类藏得很深的作用域bug。
内容的提问来源于stack exchange,提问作者Sonny
相关产品推荐
相关产品推荐

