定义变量
-
var
-
声明作用域
- 会成为包含它的函数的局部变量
function test () { var name = '小明' } test() console.log(name) // name在函数执行之后被销毁- 定义全局变量
function test () { name = '小明' } test() console.log(name) // 调用及赋值,在外面可以访问到- 注意的点
- 虽然可以通过省略var操作符定义全局变量,但不推荐这么做。
- 在局部作用域中定义的全局变量很难维护,也会造成困惑。
- 这是因为不能一下子断定省略var是不是有意而为之。
- 在严格模式下,如果像这样给未声明的变量赋值,则会导致抛出ReferenceError。
-
var声明提升
- 把变量声明提升到函数作用域的顶部
function foo(params) { console.log(age) // undefined var age = 18 } foo() 等同于 function foo(params) { var age console.log(age) var age = 18 } foo()- 可以反复使用var声明同一个变量
-
-
let
- 声明范围是块作用域
if (true) { // 块作用域 let age = 18 console.log(age) // 18 } console.log(age) // age is not defined- 不允许同一个块作用域中出现冗余声明
let age let age // Identifier 'age' has already been declared - 暂时性死区
- 在解析代码时,JavaScript引擎也会注意出现在块后面的let声明,只不过在此之前不能以任何方式来引用未声明的变量。在let声明之前的执行瞬间被称为“暂时性死区”(temporal dead zone),在此阶段引用任何后面才声明的变量都会抛出ReferenceError。
console.log(age) // let age = 18 - 全局声明
var name = '小明' console.log(window.name) // 小明 let age = 18 console.log(window.age); // undefined - for循环中的let声明
// let出现之前,for循环定义的迭代变量会渗透到循环体外部 for (var index = 0; index < 5; index++) { setTimeout(() => console.log(index), index * 1000) } // 打印5次 // 解决方案 for (var index = 0; index < 5; index++) { setTimeout(i => console.log(i), index * 1000, index) } for (var index = 0; index < 5; index++) { (i => setTimeout(_ => console.log(i), i * 1000))(index) } for (let index = 0; index < 5; index++) { setTimeout(_ => console.log(index), index * 1000) }
-
const
- 声明与let基本相似,唯一的区别是声明变量时必须同时初始化变量,修改常量的时候会报错
- const 声明变量引用的是一个对象,可以修改这个对象的内部属性
- for-of 和for-in 循环对象,推荐使用
声明风格及最佳实践
-
不使用var
- 明确了作用域
- 声明位置
- 常量,不变的值
- 重复声明
- 有助于提升代码质量
-
const优先,let次之
- 浏览器运行时强制保持变量不变
- 让静态代码分析工具提前发现不合法的赋值操作
- 提前预知会有修改的时候用let