为何bcrypt.compare的password参数取值来自user解构而非req.body?
问题原因:变量遮蔽与JavaScript块级作用域规则
这是典型的**变量遮蔽(Variable Shadowing)**问题,结合JS的块级作用域规则导致的,拆解核心逻辑如下:
先还原你的代码常见场景:
async function userAuthenticate(req) { // 外层作用域:从请求体拿到的明文密码 const { email, password } = req.body; try { const user = await User.findOne({ email }); // 内层try块作用域:从数据库用户对象解构出的哈希密码,变量名同为password const { password, ...rest } = user; // 此处的password会优先取当前块内的变量 const isMatch = await bcrypt.compare(password, user.password); } catch (err) { // 错误处理逻辑 } }
核心规则说明:
- JS采用词法作用域:变量的查找范围在代码编写时就已确定,调用
bcrypt.compare时,JS引擎会从当前所在的try块开始,向上查找第一个同名的password变量——刚好try块内刚完成该变量的声明与赋值,因此直接使用这个内层变量,不会再访问外层的请求体密码。 const/let具有块级作用域:嵌套的try块属于独立作用域,内部声明的password会“遮蔽”外层同名变量。由于调用compare前已经执行了解构赋值语句,内层变量已完成初始化,这就是你感知到“引用晚声明变量”的本质。
补充:若在同一作用域内用const重复声明同名变量会直接触发语法错误,但嵌套块内的声明属于不同作用域,只会发生变量遮蔽而非报错。
内容的提问来源于stack exchange,提问作者A.Lee
相关产品推荐
相关产品推荐

