var、let与const——(浅谈JavaScript中声明变量的三个关键字)

28 篇文章 1 订阅
3 篇文章 0 订阅

在JS中,声明变量的关键字有三种,分别是var、const和let。
其中,var在任何版本的ECMAScript中都可以使用,而let和const只能在ES6(ES2015)及之后才能使用。

var关键字

var关键字(var是一个关键字)可以定义一个变量,后跟变量名。
var具有如下几个特点:

  • 声明范围时函数级作用域
  • 存在作用域提升(变量提升)现象
  • 重复声明不报错
  • 全局声明的变量自动成为window对象的属性

案例1:使用var定义的变量会成为包含它的函数的局部变量

	function test(){
			var msg = "hello world";//此时,var定义的变量是局部变量
		}
		test();
		console.log(msg);//报错

在上面代码中,我们在函数体内用var定义了一个变量,但它会变成局部变量,只能用于函数体中。也就是说,在函数执行完成后,里面的局部变量就会被销毁,函数体外无法使用。但是,如果在函数体中删除var操作符,就可以将msg定义成全局变量,这时我们在函数体外就可以调用:

	function test(){
			msg = "hello world";//此时,var定义的变量是全局变量(不推荐这么做)
		}
		test();
		console.log(msg);//打印结果为"hello world"

案例2:var的作用域提升(变量提升)现象

使用var时,下面的代码不会报错。因为使用这个关键字声明的变量会自动提升到函数作用域顶部:

	function test(){
			console.log(msg);
			var msg = "hello world";
		}
		test();//undefined

之所以不会报错,是因为ECMAScript运行时将其等价于如下代码来执行:

	function test(){
			var msg;
			console.log(msg);
			msg = "hello world";
		}
		test();//undefined

这种现象就是所谓的“提升”(hoist)现象,也就是把所有变量声明都拉到函数作用域顶部。

let声明

let与var的作用相似,但区别很大。let有如下几个特点:

  • 声明范围是块级作用域
  • 没有提升现象,但有暂时性死区问题(TDZ)
  • 不能重复声明
  • 全局声明不是window对象的属性

案例1:let作用域仅限在块内部

所谓的块,简单来理解就是一个花括号内部就是一个块

		if(true){
			let age = 26;
			console.log(age);//26
		}
		console.log(age); //ReferenceError: age没有定义

在这里,age变量之所以不能在if块中外部被调用,是因为它的作用域仅限于该块内部。

案例2:暂时性死区(TDZ)
我们来对比一下var和let在下面情形中的不同表现:

		//name会被提升
		console.log(name);//undefined
		var name = 'Matt';
		
		//age不会被提升
		console.log(age);//ReferenceError: age没有定义
		let age = 26;

在let声明之前执行瞬间被称为暂时性死区,自此阶段引用任何后面才声明的变量都会抛出ReferenceError,而用var定义,则会出现提升现象,不会报错。

案例3:for循环中的let声明
有如下一个循环:

		for(var i = 0; i < 5; i++){
			setTimeout(function(){
				console.log(i);
			},0)
		}
		//输出结果:5,5,5,5,5

之所以会这样,是因为在退出循环时,迭代变量保存的是导致循环退出的值:5。在之后执行超时逻辑时,所有的i都是同一个变量,因而输出的都是同一个最终值。
而在使用let迭代变量时,JS引擎在后台会为每个迭代循环声明一个新的迭代变量。每个setTimeout引用的都是不同的变量实例,所以console.log输出的是我们期望的值,也就是循环执行过程中每个迭代变量的值。

		for(let i = 0; i < 5; i++){
			setTimeout(function(){
				console.log(i);
			},0)
		}
		//输出结果:0,1,2,3,4

const声明

const具有let所有特点:无变量提升、具有块级作用域、存在暂时性锁区、只允许声明一次。在此基础上,它还有如下特点:

  • 声明变量时必须初始化
  • 初始化后不可以修改
  • 不能修改仅限于常量的引用
  • 不能用于声明会自增的迭代变量

案列1:const声明的限制只适用于它指向变量的引用
const不允许被修改。但const变量引用若是一个对象,那么修改这个对象内部的属性并不违反const的限制。

const person = {};
person.name = 'Matt'; //修改成功,且不会报错

案例2:const声明迭代变量(会报错)
由于迭代变量会自增,所以会和const中不允许被修改的特点相冲突,结果会报错

for(const i = 0 ; i < 10; ++i){} //TypeError:给变量赋值

开发中最佳使用建议:

  • 不使用var
  • 优先使用const,let次之

参考书籍:《JavaScript高级程序设计(第四版)》
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值