你真的了解var、let、与const区别吗?

写在前面:在ES6发布多年后,你会发现let 和const越来越多的进入到你的视野,如何认识并使用它们是我们必须要掌握的基础知识

目录

0. var、let、与const大致区别

1. var 作为函数作用域声明

1.1 var的函数作用域

1.2 变量提升

2. 使用let的块级作用域声明

2.1 let的块级作用域

2.2 let不能在同一作用域多次声明

2.3 let的最佳应用  使用let声明的变量迭代

3. 使用const的常量声明

3.1、使用const声明的变量必须同时初始化和赋值

3.2、和let一样都具有 块级作用域的特点、在同一作用域不能多次声明。

3.3、const在它的生命周期任何时候都不能再次赋值:


0. var、let、与const大致区别

作用域声明初始化的不同独有特点
var使用函数作用域同一执行上下文可以重复声明
同一执行上下文可以重复赋值
可以先声明再赋值
变量提升
let使用块级作用域同一执行上下文不可以重复声明
同一执行上下文可以重复赋值
可以先声明再赋值
const使用块级作用域同一执行上下文不可以重复声明
同一执行上下文不可以重复赋值
不可以先声明再赋值,必须同时声明并赋值
不能重复赋值,但对象的键不受限制

1. var 作为函数作用域声明

1.1 var的函数作用域

用var声明一个变量,变量会被添加到最接近的执行上下文。所以在函数中声明,会被添加到函数的执行上下文中,如果变量没有声明就已经初始化了,那么它会自动被添加到全局上下文中(全局上下文指的就是window对象);

function demo(a,b){
    var sum=a+b
}
demo(1,2)
console.log(sum) //sum is not defined

 在demo()被调用时,声明了变量sum,sum被添加到最近的执行上下文,成为了demo函数中的局部变量。在函数执行完成后,在全局中自然是无法访问到demo函数的局部变量的

function test(){
    a=100
}
test()
console.log(a)  //100

由于调用test()后,a被添加到了全局上下文,在函数执行完成后依然可以访问;但是请注意,此种方式“未声明就开始初始化变量”是一个非常常见的错误,会导致很多问题。在严格模式下此种方式会报错。

1.2 变量提升

用var 声明的变量具有变量提升的特性,函数内var声明的所有变量在函数体内始终是可见的 。请看下面的例子

var num=12345;
function test(){
    console.log(num);  //打印`undefind`
    var num=789;    
    console.log(num);  //打印`789`
}
test();

看到上面的代码,很多同学会说:“第二次打印的结果我知道,第一次怎么不是12345?怎么不打印上面的全局变量12345 ”

实际上,根据我们提到的:函数内声明的所有变量在函数体内始终是可见的  也就是说我们在第四行代码声明的局部变量被放在了最前面,也就是如下的形式:

var num=12345;
function test(){
    var num            //声明被提前到顶部 在这里声明了局部变量 但未赋值
    console.log(num);  //打印`undefind` 在这里打印的就是上面的局部变量
    num=789;           //在这里将num初始化并赋值
    console.log(num);  //打印`789`
}
test();

因此,为了写出清晰且真实的变量作用域,请保证良好的开发习惯,请将变量声明放在函数体顶部。

2. 使用let的块级作用域声明

2.1 let的块级作用域

let 声明是在ES6中新增的,他的作用域是块级的,在引入let关键字前,javascript是没有块级作用域概念的(es6前是函数作用域)。块级作用域是由最近的一对   {   }  包裹的,下图这些都是块级作用域

if(true){
    let a
}
console.log(a); // a is not defined

let num=10
while (num<10) {
    let a
}
console.log(a); // a is not defined

function test(){
    let a
}
console.log(a); // a is not defined

{
    let a       //这并不是对象字面量,而是独立的块
}
console.log(a);    // a is not defined

2.2 let不能在同一作用域多次声明

let不能在同一作用域多次声明,var会默认覆盖

var _num=1
var _num=2

console.log(_num)   // 2


let _string='nihao'
let _string='hellow'    //错误警告:已经声明过
console.log(_string)

2.3 let的最佳应用  使用let声明的变量迭代

for(var i=0;i<10;i++){}
console.log(i)            //10

for(let j=0;j<10;j++){}
console.log(j)            //j is not defined

“严格来讲,let在javascript运行时也会被提升,但由于 暂时性死区 的缘故,实际上不能在声明前使用let变量。”

3. 使用const的常量声明

const也是在ES6中新增的,其特点是:

3.1、使用const声明的变量必须同时初始化和赋值 不能使用null占位。

const A             // 常量声明未赋值
A=10    

const B=10          // 常量声明未赋值
console.log(B)      // 10

3.2、和let一样都具有 块级作用域的特点、在同一作用域不能多次声明。

3.3、const在它的生命周期任何时候都不能再次赋值:

let obj={}
obj=12345
console.log(obj)  //12345

const OBJ2={}
OBJ2={}     //obj2已被赋值,不能再次赋值
OBJ2=12345     //obj2已被赋值,不能再次赋值

虽然说使用const声明的对象不能被再次赋值,但是如果赋值的是对象,我们是可以更改对象的键值对的;但是被Object.freeze()包裹的对象会默认失败!

const OBJ={}
OBJ.name='qin'
console.log(OBJ.name)        //qin

const OBJ=Object.freeze({})
OBJ.name='qin'
console.log(OBJ.name)        //undefined

由于const的值是单一的,并且不可修改,v8引擎将const声明的所有实例都替换成了实际的值,不用在查询表中进行变量查询;

所以在实际开发中,能使用const声明尽量使用const声明,除非你这个变量需要重新赋值;其次为了保持良好的开发习惯,我们一般将常量都使用大写

注释:本文参考《JavaScript高级程序设计 第四版》 Matt Frisbie著

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值