一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
var let const的区别
在看视频的时候只讲了用var定义变量,之后看书的时候看到了let和const。于是准备写一篇Blog。
var
-
在全局作用域用var定义的变量是全局变量,在其所有子级域中都可以使用。
-
var声明的变量存在变量提升的情况。(var的预解析)
console.log(f); var f = 2; console.log(f); //输出: //undefined //2编译器在执行阶段,会先定义变量,再顺序编译执行。
// var的变量提升涉及到有个预解析的问题,即在代码执行之前,对代码进行通读并解析。 // 1. 解析了var关键字,即变量提升,即先var 声明变量,但不赋值。 // 2. 解析了声明式函数,即声明一个变量,并定义为函数。但执行代码是按顺序执行的。 // 3. 不管if语句中的条件如何,if语句中的代码依旧会预解析。 // 4. 函数中return语句后面的var也会预解析。 // 5. 预解析中重名以函数为主 console.log(a); //输出为 undefined var a = 100; console.log(a); //输出为 100 if(false){ var b = 200; } console.log(b); //输出为 undefined function f(){ console.log('执行函数f()'); console.log(c); return ; var c = 200; //输出为 undefined } f(); console.log(c); //会报错 -
var可以重复声明一个变量。
var a = 1; console.log(a); var a = 2; console.log(a); var a = 3; console.log(a); // 输出 // 1 // 2 // 3 -
在函数内用var声明的变量是局部变量
如果函数作用域有该变量,则给自己赋值,如果没有则会给父级的变量赋值。如果全局变量都没有,则会定义一个全局变量并赋值。
//在函数作用域用var声明变量是局部变量,在父级作用域是未声明 function f(){ var a = 1; } f(); console.log(a); // 会报错//并不会影响父级作用域中a的值 var a = 2; function f1(){ var a = 1; } f1(); console.log(a); // 输出结果2//函数作用域没有该变量,所以会给父级作用域的变量a赋值 var a = 2; function f2(){ a = 1; } f2() console.log(a); // 输出结果1//全局作用域也没有变量a,所以会声明一个全局变量a function f3(){ a = 1; } f3() console.log(a); // 输出结果1
let
-
let是ES6新增的语法。用法类似于var,但声明的变量只在let所在的代码块内生效。
for(var i = 1;i < 10;i++){} console.log(i); //可以正确输出i的值,即 10 for(let j = 1;j < 10;j++){} console.log(j); //会报错 -
不存在变量提升,在用let声明一个变量前,这个变量是不存在的,如果引用就会报错。
-
暂时性死区
当代码块用let声明一个变量时,在在该代码块中在let声明变量之前,该变量都不可用。
造成该错误的主要原因是:ES6新增的let、const关键字声明的变量会产生块级作用域,如果变量在当前作用域中被创建之前被创建出来,由于此时还未完成语法绑定,如果我们访问或使用该变量,就会产生暂时性死区的问题,由此我们可以得知,从变量的创建到语法绑定之间这一段空间,我们就可以理解为'暂时性死区'
var a = 111; if(1){ console.log(a); a = 123; let a; console.log(a); } -
不能再相同作用域重复声明,但可以在不同代码块中重复声明
let a = 1; { let a = 2; console.log(a); } console.log(a); //会依次输出2 1let b = 1; let b = 2; console.log(b); console.log(b); //会报错所以不能在函数内重新声明形参。
const
-
const声明一个只读的变量,一旦声明,该变量的值不能改变。可以当做常量。而且const声明变量必须立即初始化,不然也会报错。
const a = 1; a = 2; //会报错 -
用const声明已经声明的变量也会报错。
let a = 1; var b = 1; const a = 2; const b = 2;
实际上const是保证变量指向内存地址的值是不能改动的,可以对简单数据类型,是可以当做常量的。
而对于复杂类型的数据,变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的,即实际数据的位置不变,但不能保证实际数据不被修改。
var a = 2;
const f = {a}
console.log(f);
f.a = 1;
f.b = 3;
console.log(f);
//输出为:
//{ a: 2 }
//{ a: 1, b: 3 }
其他情况,const与let是一致的。
总结
var,let,const的区别主要为以下几点:
-
变量提升
var声明的变量存在变量提升,即变量可以在声明之前调用,值为undefined。
let和const不存在变量提升,即它们所声明的变量一定要在声明后使用,否则报错。
-
暂时性死区
var不存在暂时性死区。
let和const存在暂时性死区,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
-
块级作用域
var不存在块级作用域。
let和const存在块级作用域。
-
重复声明
var允许重复声明变量。
let和const在同一作用域不允许重复声明变量。
-
修改声明的变量
var和let可以。
const声明一个只读的常量。一旦声明,常量的值就不能改变。复杂数据类型的值和结构仍然可以修改。