本文已参与「新人创作礼」活动,一起开启掘金创作之路。
注意: 本文的示例代码结果都是在node环境下运行的结果,node版本:V12.19.0。
关于var、let、const这三者的区别,我们先来说说var和let的区别,最后再说const。
1. 作用域不同
let关键字声明:
如果是在代码块中声明的变量,那么只能在代码块中访问,在代码块外面是无法访问该变量的,这也就是ES6为我们带来的块级作用域。
var关键字声明:
如果在代码块中声明的变量,那么在代码块外面依然可以访问该变量,也就是说块级作用域对于var声明的变量是没有限制的。
能够限制var关键字声明变量的作用域是函数作用域,如果var在函数内部声明变量,那么它会作为局部变量存在,函数外部是无法访问的。当然,这条规则也适用于let关键字声明的变量
示例代码如下
function test(flag) {
if (flag) {
var name = '娜个小部';
}
// 使用var关键字在代码块中声明的变量,在代码块外面依然可以访问。
console.log(name); // 娜个小部
}
test(true);
// 函数体内部使用var关键字声明的变量,在函数外部无法访问
console.log(name) // ReferenceError: name is not defined
/**************不怎么华丽的分割线***************/
function test(flag) {
if (flag) {
let name = '娜个小部';
}
// 使用let关键字在代码块中声明的变量,在代码块外面是无法访问的。
console.log(name); // ReferenceError: name is not defined
}
test(true);
// 函数体内部使用let关键字声明的变量,在函数外部无法访问
console.log(name); // ReferenceError: name is not defined
2. 变量提升
使用var关键字声明的变量存在变量提升,而使用let关键字声明的变量不存在变量提升的问题。
这里解释下什么叫做提升(hoist):就是将var关键字声明的变量全部拉到当前作用域的最顶部。
示例代码如下
function test(flag) {
var name; // 先定义
if (flag) {
name = '娜个小部'; // 重新赋值
}
console.log(name); // 娜个小部
}
test(true);
3. 冗余声明
这个很好理解,var关键字声明的变量可以重复声明,而let关键字声明的变量不可以重复声明。
示例代码如下
// var关键字声明的变量可以重复声明
function test() {
var age = 18;
var age = 28;
var age = 38;
console.log(age) // 38
}
test();
// let关键字声明的变量不可以重复声明, 如果重复声明会报错
function test() {
let age = 18;
let age = 28; // SyntaxError: Identifier 'age' has already been declared
let age = 38;
}
test();
4. 暂时性死区
由于let关键字声明的变量不会在作用域中被提升,所以在解析代码时,JavaScript引擎也会注意出现在块后面的let声明,在此之前不能以任何方式来引用未声明的变量。在let声明之前的执行瞬间被称为暂时性死区(temporal dead zone),在此阶段引用任何后面才声明的变量都会抛出ReferenceError。
示例代码如下
conole.log(name); // 报错
// conole.log(typeof name); // 报错
let name = '娜个小部';
5. 全局声明
var关键字声明的变量,在全局作用域中会作为window对象的一个属性存在。 let关键字声明的变量则不会作为window对象的属性存在,不过let声明的全局变量依然是在当前页面的声明周期内存续的。
注意下面的示例代码是在浏览器环境下运行的,node环境全局对象为global, var 和let 二者声明的变量都不会作为global属性存在
var name1 = '娜个小部';
let name2 = '娜个小部呀!';
console.log(window.name1); // 娜个小部
console.log(window.name2); // 娜个小部呀
6. 条件声明
var关键字声明的变量由于存在变量提升,所以JavaScript引擎会自动将多余的声明在作用域顶部合并为一个声明。而let关键字声明的变量的作用域是块,因此它不可能检查前面是否已经使用let声明过同名变量了,即let关键字无法使用条件声明模式。
示例代码如下
if (typeof name1 === 'undefined') {
let name1;
}
// 上面代码 如果name不存在,则声明一个name,因为name是在块中声明的,所以下面这句代码就相当于声明了个全局变量。
name1 = '娜个小部';
console.log(window.name1); // 娜个小部
let与const的区别
其实let与const非常相似,我列举一下,大家可以感受下:
- 都不能变量提升
- 作用域都是块级作用域
- 都不能重复声明
不同点是let声明的是变量,而const声明的是常量,声明后不能修改,如果修改会导致运行错误。
如果const声明的常量是一个引用类型,那么修改这个常量里面的属性值不会导致运行错误。
for(const i = 0; i < 10; i++) {} // 报错了,因为i是一个迭代变量,会自增;
const params = {
name: '娜个小部';
age: 18
};
params.name = '猜猜我是谁'; // 不会报错
本文已结束,拜拜喽!