var,let,const区别

目录

前言

一、作用域

var声明变量的作用域

let声明变量的作用域

const声明变量的作用域

二、变量提升

var声明的变量和函数存在变量提升

let和const声明的变量和函数不存在变量提升

三、暂时性死区

四、重复声明

let和const在同一作用域内,相同的变量不可以重复声明

var在同一作用域内,相同的变量可以重复声明变量

五、全局属性

六、初始值

七、for循环中的循环变量


前言

var、let、const都是javascript声明变量的关键字,在ES6之前的版本中,用于声明变量的关键字只有var,并且没有块级作用域,只有函数作用域和全局作用域,但在ES6中已改变这种状况。ES6引入了let和const两个关键字,它们既可以用于声明变量,还能够将变量绑定到当前所处的任意作用域中,换句话说,就是把变量的作用域封闭在所处的代码块(即花括号字符“{”和“}”之间的区域,例如if条件语句中的代码)中,如此一来就形成了块级作用域。引入块级作用域解决了这两个问题:1.内层变量可能覆盖外层变量,2.用来计数的循环变量泄露为全局变量两个问题。下文会说明let和const两个关键字与var之间的不同。

一、作用域

var声明变量的作用域

var声明的变量不存在块级作用域,属于全局作用域。但是存在函数作用域,在函数中用var声明的变量在函数外不能使用,也不能跨函数使用(在其他函数里使用)。

if(true){
            var num=1
        }
        console.log(num);//输出结果是1,说明变量是全局的
        function add(num){
            var num1=2
            return num+num1
        }
        console.log(add(num));//输出结果3,说明变量是全局的
        console.log(num1);//输出ReferenceError: num1 is not defined,存在函数作用域

let声明变量的作用域

let声明的变量存在块级作用域,由{ }包裹,不能跨块访问。也存在存在函数作用域,在函数中用let声明的变量在函数外不能使用,也不能跨函数使用(在其他函数里使用)。

if(true){
            let num=1
        }
        console.log(num);//输出ReferenceError: num is not defined,存在块级作用域
        function add(num){
            let num1=2
            return num+num1
        }
        console.log(add(num));//输出结果3,说明变量是全局的
        console.log(num1);//输出ReferenceError: num1 is not defined,存在函数作用域

const声明变量的作用域

const声明的变量存在块级作用域,由{ }包裹,不能跨块访问。也存在存在函数作用域,在函数中用const声明的变量在函数外不能使用,也不能跨函数使用(在其他函数里使用)。

 if(true){
            const num=1
        }
        console.log(num);//ReferenceError: num is not defined,存在块级作用域
        function add(num){
            const num1=2
            return num+num1
        }
        console.log(add(num));//输出结果3,说明变量是全局的
        console.log(num1);//输出ReferenceError: num1 is not defined,存在函数作用域

内层变量可能覆盖外层变量\n用来计数的循环变量泄露为全局变量

二、变量提升

var声明的变量和函数存在变量提升

变量提升又称声明提前:JavaScript 引擎会在执行代码之前先进行一次预编译(预解析),把所有的 var 变量声明和函数声明提升到当前作用域的顶部。如下代码所示:

console.log(num) // 输出undefined而不是ReferenceError: num is not defined说明num已被定义但未赋值
        var num = 1
        function Test() {
            console.log(num1) // 输出undefined而不是ReferenceError: num1 is not defined
            var num1 = 2
            console.log(num1);//输出2
        }
        Test()
        console.log(num) // 输出1

经过预解析实际后代码如下:

        var num
        function Test() {
            var num1
            console.log(num1) // 输出undefined而不是ReferenceError: num1 is not defined
            num1 = 2
            console.log(num1);//输出2
        }
        console.log(num)
        num=1
        Test()
        console.log(num)

let和const声明的变量和函数不存在变量提升

let声明

console.log(num) // 输出uReferenceError: Cannot access 'num' before initialization
        let num = 1

const声明 

 console.log(num) // 输出uReferenceError: Cannot access 'num' before initialization
        const num = 1

三、暂时性死区

暂时性死区是指在代码块内,使用let或const命令声明变量之前的区域,该变量在此区域内是不可用的,即属于该变量的“死区”。

因为let,const不存在变量提升所以导致死区的形成,但是var不存在暂时性死区的情况。

在ES6中,暂时性死区的概念是为了防止在变量声明前就使用这个变量,从而导致意料之外的行为。具体来说,当在代码块内尝试访问一个使用let或const声明的变量,但在该声明之前就已经引用了这个变量时,会触发一个ReferenceError错误。可以看如下代码方便理解:

	let a = 1
    {
      //死区开始
      
      console.log(a) //死区:因为存在块级作用域无法访问外部的a,也无法访问到内部的a
      
	  //死区结束
      let a = 2 //此区域块内创建了a并绑定了值
      console.log(a)//此时获取到内部的a
    }

四、重复声明

let和const在同一作用域内,相同的变量不可以重复声明

let同一作用域下:

        let num=1
        let num=2 //报错SyntaxError: Identifier 'num' has already been declared
       

const同一作用域下: 

        const num=1
        const num=2 //报错SyntaxError: Identifier 'num' has already been declared

let、const同一作用域下 :

        let num=2 
        const num=1 //报错SyntaxError: Identifier 'num' has already been declared

不同作用域下:

        let num=1
        if(true){
            let num=1//不报错
        }

var在同一作用域内,相同的变量可以重复声明变量

var num=1
var num=2//不报错

五、全局属性

var关键字声明的变量会挂载到window全局属性上,但是let和const声明的则不会。

        const name='张三'
        console.log(window.name);//无
        let age=13
        console.log(window.age);//undefined
        var hobby='唱歌'
        console.log(window.hobby);//唱歌

六、初始值

1、使用const定义变量时必须赋予其初始值,而var和let则不用

const a//'const' declarations must be initialized
a=1//这种方式是不正确的

const a=1//必须对其赋值

2、const声明的常量必须进行初始化,不允许对常量重新赋值

const a=1
a=2//错误,不能重新赋值 TypeError: Assignment to constant variable.

3、如果const定义的是一个复杂数据类型,可以添加、删除、修改值,但不能改变原有类型

const arr=[1,2,3]
        arr[0]=4//可以修改值
        arr={
            name:'张三',
            age:13
        }//错误,不可以修改原有类型

七、for循环中的循环变量

用var定义的迭代变量会渗透到for循环的外部,但用let定义变量可以解决这个问题。

for (var i = 0; i < 5; ++i) { 
 
} 
console.log(i); // 5,var定义的for循环的迭代变量渗透到外部

解决办法改用let,变量i只存在于当前作用域: 

for (let i = 0; i < 5; ++i) { 
} 
console.log(i); // ReferenceError: i 没有定义,let定义的循环变量不会渗透到外部

使用setTimeout定时器迭代用var定义循环变量可能会出现以下问题:

for (var i = 0; i < 5; ++i) { 
 setTimeout(() => console.log(i), 0) 
} 
// 你可能以为会输出 0、1、2、3、4 
// 实际上会输出 5、5、5、5、5

之所以会这样,是因为在退出循环时,迭代变量保存的是导致循环退出的值:5。同步执行完执行异步代码:在执行setTimeout时,所有的 i 都是同一个变量,因而输出的都是同一个最终值。

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

而在使用 let 声明迭代变量时,JavaScript 引擎在后台会为每个迭代循环声明一个新的迭代变量。每个 setTimeout 引用的都是不同的变量实例,所以输出的是我们期望的值,也就是循环执行过程中每个迭代变量的值。


参考文献:【var、let、const的区别 - CSDN App】http://t.csdnimg.cn/w432v

  • 16
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值