JavaScript基础——var、let、const和作用域

      相比ES5中单一的var定义变量方式,ES6发展成var、let、const三种,前端人员在面试时也经常被问到let和var的区别,这里参考了阮一峰老师的es6和其他博文对这三种命令简单总结一下,如有错误欢迎指正,与君共勉。

 

一、作用域

1. 为方便后面的理解,这里先简单介绍一下作用域,我对作用域的理解是,

  • 只会对某个范围产生作用,而不会对外产生影响的封闭空间。
  • 在封闭空间里,外部不能访问内部变量,但内部可以访问外部变量。

2. js中的作用域有:

(1)ES5里只有两种作用域:全局作用域和函数作用域,且函数作用域内声明的变量由于存在hoisting,它的有效范围是整个函数体,如果对下面代码的输出结果有疑问,可结合JavaScript基础——ES5变量提升(Hoisting)理解。

//定义全部变量
var a=2;
//定义外部函数
function outer(){
    //访问全部变量
    console.log(a);
    //定义内部函数
    function inner(){
        console.log(a);
        var a=10;
        console.log(a);
    }
    inner();
    console.log(a);
}
outer();

//输出结果:
2
undefined
10
2

(2)ES6除了上面两种,还新增了块级作用域,即最近的花括号所涵盖的范围。

注意:对类似 a=10; 这种给尚未声明的变量赋值的语句,会使得该变量a自动成为全局变量。但在"use strict"定义的严格模式下,不允许使用未声明的变量。

 

二、var、let的区别

如图,本文总结了var和let的5点区别,分别是:块级作用域、变量提升、暂时性死区、重复声明和window全局访问

                           

 

1. let声明的变量拥有块级区域

{
    var a=1;
    let b=2;
}

console.log(a);
console.log(b);

//输出结果:
1
Uncaught ReferenceError:b is not defined

let声明的变量b作用域为块级,因此在花括号之外访问会报错,而var声明的变量a最小的作用域也是函数作用域,因此可以正常输出。

 

2. let不存在变量提升

由于var变量具有变量提升的特性,因此变量可以先使用后声明,而let所声明的变量一定要在声明之后使用,示例如下:

console.log(a);
var a=1;

//输出结果:
undefined
console.log(b);
let b=2;

//输出结果:
ReferenceError

 

3. let有暂时性死区(temporal dead zone,简称TDZ)

只要块级作用域内存在let、const命令,它们所声明的变量就绑定这个区域,不再受外部的影响。并且该区域内,使用let或const命令声明变量之前,该变量都是不可用的,我们把这种语法称为暂时性死区

示例一:

var tmp=1;
if(true){
    tmp=2;    //ReferenceError
    let tmp;
}

let声明的变量tmp需要先声明再使用,因此上面的代码报错。

示例二:

if(true){
    // TDZ开始
    tmp=1;
    console.log(tmp);    //ReferenceError

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

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

上面这段代码,在let对变量声明之前,都属于tmp的“死区”,会出现ReferenceError.

 

4. let不允许重复声明

当用var重复声明变量时,变量只会在最顶部开始的地方声明一次,后面的声明都会被忽略,仅用于赋值。

var a=1;
console.log(a);
if(true){
    var a=10;
    console.log(a);
}
console.log(a);

//输出结果:
1
10
10

let不允许在相同作用域内,重复声明同一个变量,也不能在函数内部重新声明参数。

//抛出语法错误:SyntaxError
function func(){
    let a=1;
    var a=2;
}

//抛出语法错误:SyntaxError
function func(){
    let a=1;
    let a=2;
}

 

5. let声明的全局变量不是全局对象的属性

也就是说,不能通过window.变量名的方式访问该变量

 

三、const

ES6中新增了const关键词,const就是用来定义常量的,常量名习惯大写,遵循的规则有,

  • const声明的常量不得改变值
  • 声明的同时,必须初始化赋值
  • 和let一样:块级作用域+没有hoisting+TDZ+不可重复声明

猜你喜欢

转载自blog.csdn.net/huaf_liu/article/details/108963422