知识卡片
函数作用域下的声明提前机制
内容
JavaScript没有块级作用域(if、for花括号内声明的变量不是只在花括号内可见),取而代之的是函数作用域:一个变量在它所在的整个函数体内都是有定义的,不论它写在函数体的哪个位置。这带来一个反直觉的现象——声明提前(hoisting):函数体内用var声明的变量,其”声明”动作会被提升到函数顶部,但”赋值”动作留在原处不动。所以在赋值语句之前读取该变量,得到的不是报错也不是外层同名变量的值,而是undefined,因为局部变量已经存在但尚未赋值,把外层同名变量遮蔽了。这也是为什么有经验的JS程序员习惯把所有var声明集中写在函数顶部——不是代码风格偏好,而是让代码书写顺序如实反映变量提升后的真实作用域,减少心智负担。
参考来源
《JavaScript权威指南(原书第6版)》第3章《类型、值和变量》