表达式求值机制解析:为何x * --x输出6而非4?
为什么
x * --x 会输出6而不是4? 这是个JavaScript里很典型的运算顺序问题,咱们一步步拆解清楚:
1. 表达式 x * --x 的执行逻辑
当你运行这段代码时:
let x = 3 console.log(x * --x) // 输出6而非4
JavaScript引擎的执行步骤是这样的:
- 首先,引擎会从左到右解析表达式的所有操作数。左侧的第一个
x会先被求值,此时x的原始值还是3,这个值会被暂存起来; - 接着处理右侧的
--x:这是前置自减运算符,它会先把x的值修改为2,再返回这个新值; - 最后执行乘法运算:用之前暂存的3,乘以刚得到的2,结果自然是6。
你提到的“缓冲区复制值”思路其实很接近本质——JavaScript在处理这类表达式时,会先获取左侧操作数的当前值,再处理右侧带自增/自减的操作数,毕竟运算符优先级(前置自减高于乘法)和操作数求值顺序(从左到右)在这里是共同起作用的。
2. 递归阶乘中的类似现象
再看这个阶乘函数:
function factorial(x) { if(!x) return 1 return x * factorial(--x) }
比如调用factorial(3)时,执行流程是这样的:
- 第一次调用:x=3,先取当前x的值3,然后执行
--x把x改成2,再进入下一层递归; - 第二次调用:x=2,同样先取当前值2,再把x改成1,进入递归;
- 第三次调用:x=1,取当前值1,把x改成0,进入递归;
- 第四次调用:x=0,返回1;
- 最后回溯计算:11=1 → 21=2 → 3*2=6,最终得到结果6。
这里的关键是每一层递归都有自己独立的变量上下文,当前函数栈里的x初始值会先被取出用于后续乘法,之后对x的修改只会影响当前栈帧和下一层递归,不会改变已经取出的那个值。
简单总结:这类问题的核心是操作数求值顺序和自增/自减运算符的副作用时机——自增/自减会修改变量,但操作数是按从左到右顺序求值的,先拿到的是变量修改前的值,后续的修改不会影响这个已经被暂存的值。
内容的提问来源于stack exchange,提问作者Ben Aston
相关产品推荐
相关产品推荐

