JS中的变量声明—var let const

ES6之前,JS都只用var声明变量。ES6不仅增加了let和const两个关键字,而且还让这两个关键字压倒性的超越var成为首选。

1.var

使用var声明变量,变量会被自动添加到最近的上下文(作用域)。

  如在函数中,最近的上下文就是函数的局部上下文。如果变量未经声明就被初始化了,那么它就会自动被添加到全局上下文:

        function add(a,b){
            var sum = a + b
            return sum
        }

        let res = add(1,2)  // 3
        console.log(sum);   // 报错undefined

说明:

  • 函数add()定义了一个局部变量,保存加法的操作。这个值作为函数的值返回,由于使用了var关键字,这个sum变量的作用域在函数内,所以在函数外是无法访问的。

如果省略add()函数内的var关键字,sun就可以访问了:

        function add(a,b){
             sum = a + b
            return sum
        }

        let res = add(1,2)  // 3
        console.log(sum);   // 3

说明:

  • sum并没有使用var声明。在调用add()之后,sum被添加到了全局上下文,在函数退出后依然存在,因此函数外可以访问

注意:

  • 未经声明而初始化变量会导致JS中的很多问题,因此初始化变量之前一定要先声明变量

var声明会被拿到函数或全局作用域的顶部——变量提升

就类似于:

var a = 1
// 相当于
var a
a = 1

如在一个作用域内,一个变量的调用在变量的声明之前的话,那么这个变量拿到的就是undefined:

console.log(a)  // undefined
var a = 1
// 相当于:
var a 
console.log(a) 
a = 1

2.let

let的作用域是块级的。块级作用域由最近的一对包含花括号{}界定的。即:if、while、function、单独的块也是let声明变量的作用域

在一个if、while中使用var 声明的变量,在这个循环外面还是可以访问到的。let就是解决了这个问题。在块级作用域内使用let声明的变量是无法在循环外访问的。

一个非常经典的笔试题:

for(var i = 0 ;i <= 5; i++){
    setTimeout(()=>{
        console.log(i)
    },0)
}
// 6 6 6 6 6 6

for(let i=0;i<=5;i++){
    setTimeout(()=>{
        console.log(i)
    },0)
}
// 0 1 2 3 4 5

说明:

  • 使用var声明的变量,加上块级作用域,每一次i++都是在同一个全局的i上面进行增加的。所以在调用栈中的主程序执行结束再逐个执行打印i的操作都是打印的循环结束以后的i(6)
  • 使用let声明的变量,块级作用域(循环语句)以外是无法访问的,每次的定时器执行的打印操作打印的都是当前循环的i的值
  • 这里说的不太透彻,配合let声明的变量没有变量提升这个特点,可以理解为let声明的for循环内是一个闭包,外界无法访问。

let声明的另一个特点:同一个变量不能用let声明两次

3.const

使用 const 声明的变量必须同时初始化为某个值。一经声明,在其生命周期的任何时候都不能再重新赋予新值。

注意:开发实践表明,如果开发流程并不会因此而受到很大影响,就应该尽可能多的使用const声明。

原文地址:https://www.cnblogs.com/codexlx/p/14275961.html