var、let、const的区别

变量提升问题

这是个老生常谈的问题了,我们再回顾一下

console.log(a); // undefined
var a = 10;
console.log(a); // 10
复制代码

这段代码会依次输出 undefined、10。那为什么会这样呢?我们简单的来分析一下实际代码执行的过程,由于var存在变量提升,也就是说会把用var声明的变量,提升到代码的最上头,不过这是时候仅仅是声明而没有赋值,所以a的默认值是undefined

var a;
console.log(a);
a = 10;
console.log(a);
复制代码

而let则不存在变量提升的问题,它是真正的从上到下依次执行的。在变量未声明之前,是无法访问的。

作用域:起作用的范围

  1. 先看一下var的作用域
if(true){
	var a = 10;
}
console.log("a=" + a); // a=10

function fn(){
	var b = 20;
} 
console.log("b=" + b); // b=undefined
复制代码

这个时候会发现,大括号根本拦不住var变量,只有function才可以拦住,也就是说var起作用的范围,要么在函数内,要么在函数外,有多层函数嵌套的情况如下

function fn1(){
	var a = 10;
	console.log(b);// undefined
	function fn2(){
		var b = 20;
		console.log(a);// 10
	}
}
复制代码

就像洋葱一样,一层套一层,在内层可以访问到外层的变量,而在外层是无法访问到内层的变量。

如果var声明的变量不存在任何一个函数里,那么它可以起作用的范围就是全局作用域。

  1. 在看一下let的作用域
if(true){
	let a = 10;
}
console.log("a=" + a); // 报错

function fn(){
	let b = 20;
} 
console.log("b=" + b); // 报错

if(true){
	let c = 30;
	console.log("c=" + c);// 30
}
复制代码

可以看到不仅被function拦住了,也被大括号拦住了。let和var比起来,起作用的范围又受到了大括号的限制,这种大括号包裹的范围,称之为块级作用域

当有像洋葱一样的一层套一层的块级作用域时

{
	let a = 10;
	console.log("b=" + b);// 报错
	{
		let b = 20;
		console.log("a=" + a);// a=10
	}
}
复制代码

同样的,内层可以访问外层的变量,而外层无法访问到内层的变量

重复声明

var可以在同一作用域内重复声明变量,由于变量提升的问题,多次声明var变量和一次声明var变量其实是一样的。

var a = 10;
var a = 20;
var a = 30;
console.log(a);// 30
复制代码

let不允许在同一作用域内重复声明变量

顶层对象的属性

通过var声明的全局变量,会默认挂载在顶层对象的属性上,在浏览器里顶层对象是window

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

let b = 20;
console.log(window.b);// undefined
复制代码

let和const的区别

let和const行为类似,唯一区别是let的值是可以变的,const声明的常量是只读的,值是不能改变的。

const a = 10;
a = 20;// 报错
复制代码

const的本质,引用阮一峰老师的话是

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。

const a = { name: "GIAO哥" };
a.name = "GIAO弟";
console.log(a.name);// "GIAO弟"
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享