var、let、const 相关

var(ES5)let,const(ES6)

1. 作用域?

简单来说,作用域就是一个独立的地盘,外层作用域无法读取内层作用域的变量,但是内层作用域可以访问外层作用域的变量或者定义外层作用域的同名变量。

2. var 变量提升? var 特点?

无论在全局作用域还是在局部作用域中,使用 var 关键字声明的变量都会被提升到该作用域的最顶部,这就是我们常说的变量提升

在代码预编译的时候,JavaScript 引擎会自动将所有代码里面以var 关键字声明的语句提升到当前作用域的顶端

function fn1() {
var name = "jack"
}

// 等价于
function fn1() {
var name;
name = "jack"
}
console.log(name) // undefined
var name = "jack"

var 的特点

  • 存在变量提升

  • 在变量未赋值时,变量为 undefined

  • 一个变量可以多次声明,后面的声明会覆盖前面的声明

  • 在函数中使用 var 声明变量的时候,该变量是局部的(因为在使用 var 声明变量时,变量会被自动添加到最接近的上下文。在函数中,最接近的上下文就是函数的局部上下文)

    function add(num1, num2) {
    var sum = num1 + num2;
    return sum
    }
    let result = add(10, 20) // 30
    console.log(sum) // 报错 sum is not defined

    如果函数内不使用 var 声明,该变量是全局的,sum 被添加到全局上下文(window)window.sum

    function add(num1, num2) {
    sum = num1 + num2;
    return sum
    }
    let result = add(10, 20) // 30
    console.log(sum) // 30

3. let

  • let 不存在变量提升,let 声明变量前,该变量不能使用(暂时性死区)

  • let 为块级作用域,所有外面的语句块访问不到

    console.log(value)  // 报错
    let value = 'hello'
  • let 不允许重复声明,如果在同一个作用域中某个变量已经存在,再次使用 let 关键字声明的话会报错

4. const

与 let 没什么大不同

  • const 声明的是常量,常量就是一旦定义完就不能修改的值。

  • 必须初始化值,否则会报错。

  • 需要注意的是:const 变量不能再被重新赋值为其他引用值,但对象的键不受限制

    也就是说,并不是变量的值不能改动,而是变量指向的那个内存地址不得改动

    const obj1 = {}
    obj1 = {} // 报错,不能给常量赋值

    const obj2 = { name: "jack" }
    obj2.name = "tony" // 没问题

5. 暂时性死区?

如果区块中存在 let 和 const 命令,以这个命令声明的变量从一开始就形成了封闭作用域。凡是在声明之前就是用这些变量,就会报错

总之,在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。这在语法上,称为 “暂时性死区”(temporal dead zone 简称 TDZ )

if (true) {
// TDZ 开始
tmp = "abc";
console.log(tmp); // 报错

let tmp; // TDZ 结束
console.log(tmp)

tmp = 123;
console.log(tmp); // 123
}

上面代码中,在 let 命令声明变量 tmp 之前,都属于变量 tmp 的死区

6. 在 for 循环中使用 var,let 的区别

for(var i = 0;i<10;i++){
setTimeout(function(){
console.log(i)
},100)
} // 输出全是10
// 因为 i 是全局变量,最后访问的都是全局变量
for(let i = 0;i<10;i++){
setTimeout(function(){
console.log(i)
},100)
} // 0123456789;
// i 是局部变量,每次循环改变的是对局部变量赋值