ES6 var let const

介绍

本文是在学习ES6时做的一些学习笔记,所有的笔记请查看:ES6 学习笔记
在初学习JS时,对于变量声明所使用的 var 、let、const等关键字觉得很简单,其实这三种声明变量的方式中有很多细节需要注意,如果不注意这些细节,可能会在我们今后的学习更深入的内容时造成很多困惑。

var let const 的一些区别

首先介绍一下全局作用域、函数作用域、块级作用域:

ES5 中作用域有:全局作用域、函数作用域(只能在定义的函数中使用)。没有块作用域的概念。

ES6 中新增了块级作用域。块作用域由 { } 包括,if语句和 for语句里面的{ }都属于块作用域。

var、let、const三种声明变量方式主要有以下几个区别:

1、var 声明的变量有变量提升,let声明的变量没有变量提升

使用var声明变量

console.log(a); //undefined
var a = 10;

等价于如下这种方式,对变量进行了提升:

// 变量进行了提升
var a;
console.log(a);//undefined
a = 10;

使用let声明变量没有变量提升,当进行如下声明时会直接报错:

console.log(b);//error:b is not defined
let b = 20;

2、var变量可以重复声明一个变量,let变量不可以重复声明同一个变量。

// 如下,当使用var重复声明同一个变量时,不会报错
var a = 10;
var a = 20;
 
 // 使用let重复声明同一个变量会报错
let b = 10;
let b = 20;//error : Identifier 'b' has already been declared

3、var变量是函数作用域(function scope) ,即其作用域是在函数范围内,否则为全局作用域。当在函数中使用var 关键字声明变量时,其作用域为函数内;如果不是在函数中使用var声明变量,则其作用域为全局的。

4、const、let为 块作用域(block scope)。 其含义为当在函数、if(){}块中、
{ } 中使用let、const声明变量时,变量只能在这些块中起作用,不会泄露成为全局作用。

针对上述两个区别,示例如下:

// var 为函数作用域,则使用var在if块中声明的变量会成为全局变量
// 在if块之外也可以访问
if(true){
    var a = 12;
}
console.log(a);// 12
 
// let为块作用域,在if块中声明的变量只能在if块中使用
if(true){
    let b = 123;
}
console.log(b);//  error : b is not defined

{
  let c = 10;
  var d = 1;
}
如下所示,输出为undefined,使用let在块中声明的变量只能在代码块中使用
console.log(c)

如下所示使用var声明在代码块中的数据,可以在代码块外访问
console.log(d)
// 如下代码所示,在for循环中使用var声明的变量,但其作用域为全局作用域
// 所以最后输出i都是相同的,都为5
//结果 5 5 5 5 5
for( var i=0;i<5;i++){       
     setTimeout(function() {
        console.log(i);
     }, 100)
}

上面代码中,变量i是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变,而且setTimeout()函数是得for循环结束完后,setTimeout()才开始执行,所以最终的i的值都为5

// let声明的变量为块级作用域
for( let i=0;i<5;i++){
     setTimeout(function() {
        console.log(i);
     }, 10)
}
// 结果 0 1 2 3 4

上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

如果使用let,声明的变量仅在块级作用域内有效,最后输出的是 6。

由于 var 命令的变量提升机制,var 命令实际只会执行一次。
而 let 命令不存在变量提升,所以每次循环都会执行一次,声明一个新变量(但初始化的值不一样)。
for 的每次循环都是不同的块级作用域,let 声明的变量是块级作用域的,所以也不存在重复声明的问题。
let生命变量的for循环里,每个匿名函数实际上引用的都是一个新的变量

进一步详细解释:
https://www.cnblogs.com/echolun/p/10584703.html

let也存在临时性死区,但是在未声明之前就是用let,会报reference错误,因为let存在临时性死区。

4、var、let 声明的变量可以重新赋值、const声明的变量不可以重新赋值,且必须在声明时进行初始化。

5、const声明的对象,对象不可重新赋值,但对象属性可以重新赋值,如果使用 Object.freeze()函数,可以使得属性值也不可以改变

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值