var、let和const之间的那些事儿

208 阅读3分钟

一、作用域

在说定义之前,先说一个作用域的问题,作用域又分函数作用域和块级作用域。

1、函数作用域

函数作用域呢,就是指函数内部,在函数内部中定义的东西在函数外无法访问,比如下面这段

function Test(){
    var temp = '函数内变量';
}

//此处想要访问temp变量就访问不到
console.log(temp);

2、块级作用域

块级作用域,即大括号{}之间的区域,此处多是指以下几种情形

// 条件语句
if () {}

// switch语句
switch () {}

// for / while循环语句
for () {}
while () {}

// try...catch语句
try () catch (err) {}

// 单大括号
{}

二、var和let

之前已经说过了作用域了,那么这里直接说,var的作用域是函数作用域而let的作用域是块级作用域。

1、var

函数内部用var定义的变量仅在函数内部可以访问,在函数外部无法访问。就如下面这段代码所示

function Test() {
    var temp = 5;
    console.log('inside ' + temp);
}
Test();

console.log('outside ' + temp);    // 此处会报错

最后一个log语句会报错提示temp变量没有被定义,因为你在函数外是访问不到函数内部用var定义的变量的。但是在{}内部,即块级作用域内用var定义的变量是可以跨越作用域被访问到的,下面这段代码就会正常的进行打印

if (true) {
    var temp = 5;
    console.log('inside ' + temp);
}

console.log('outside ' + temp);    // 正常打印结果

2、let

{}块级作用域内部用let定义的变量仅在作用域内部可以访问,在作用域外部无法访问。就如下面这段代码所示

if (true) {
    let temp = 5;
    console.log('inside ' + temp);
}

console.log('outside ' + temp);    // 此处会报错temp变量没有被定义

但是同样的在函数作用域内部用let定义的变量在函数外也是无法访问的,此处大致可以看出二者的关系应该为

截屏2021-06-16 上午10.08.31.png

3、变量提升和暂时死区

var声明的变量,无论实际声明的位置在何处,都会被视为声明在函数的顶部,如果不在函数内,则视为在全局作用域的顶部。而let和const则没有这个变量提升,当提前调用了let或const声明的变量(或常量)时,则会报错“不能在初始化之前访问”。例如下面的代码

console.log(temp);    // 不会报错,打印unfined
var temp = 5;
console.log(temp);    // 打印5

console.log(temp1);    // 报错,“不能在初始化之前访问”
let temp1 = 5;
console.log(temp1);    //不会执行,因为前面已经暂时性死区

为什么会这样呢?因为javascript引擎工作方式是先预解析,获取所有被声明的变量和函数,再一行行地执行,这样所有变量声明都会被提升到头部,这就是变量提升。

三、const

const,即为常量的定义,常量必须先声明再访问,与let一样不存在变量提升。常量声明时必须进行初始化,如const temp = 5;,否则就会报错“const声明中缺少初始化式”。

1、const的不变

常量,顾名思义,对它进行了初始化之后是无法再进行改变的。

const temp = 5;
temp = 6;    // 报错,“对常量变量的赋值”

2、const的变

这里的变不是说违反了上一条所说的。先看下面这段代码

const person = {
    name: '韩梅梅',
    age: 14
}
console.log(person);

person.age = 15;
console.log(person);    // 此处打印结果可看出韩梅梅的年龄已经变为15岁

person = {
    name: '李雷',
    age: 16
}
console.log(person);    // 报错,因为person为常量变量无法重新赋值

由此可以看出,我们改变的实际上并不是const声明的常量变量指向的对象,而是指向对象当中的某个属性。而对常量变量本身的重新赋值依旧是不被允许的,所以没毛病。

四、写在最后的一些话

这里是学习路上的一些记录备忘,所以难免会不够准确甚至错误。欢迎大家路过指正。