js中var、const、let之间的区别以及作用域

一、前言:

要说他们的区别,首先需要了解作用域的概念

作用域永远都是任何一门编程语言中的重中之重,因为它控制着变量与参数的可见性与生命周期。js中的作用域一共有两种(块级作用域与函数作用域)首先先理解下这两个概念

  • 块级作用域:任何一对花括号 {} 中的语句都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。比如if(){} ,for(){}中的花括号都是块级作用域

  • 函数作用域:很明显是function(){}的形式,定义在函数中的参数和变量在函数外部是不可见的

关于这块的总结
var:var是忽略块级作用域的,意思就是说,在块级作用域中用var定义的变量,在块级作用域外依然可以访问,var只有在函数作用域中声明,外部才不能访问;
let/const:这两种方式是在es6时提出的,所以这两种方式都是有块级作用域一说的

对于这块,我们可以来看几个Demo:

Demo1:

/*---------在块级作用域中,分别用var/const/let三种方式定义的变量a---------*/

if( true ) {
	var a=1; 
	console.log(a)     //当然是1
}
console.log(a)         //答案也是1,因为对var来说没有块级作用域
--------------------------------------------------------------------------
if( true ) {
	const a=1;  
	console.log(a)     //当然是1 
}
console.log(a)         //答案是Uncaught ReferenceError: a is not defined,用const定义的变量a只能在块级作用域内部访问,外部访问不了
--------------------------------------------------------------------------
if( true ) {
	let a=1;       
	console.log(a)     //同样也是1 
}
console.log(a)         //答案是Uncaught ReferenceError: a is not defined,用let定义的变量a只能在块级作用域内部访问,外部访问不了


/*---------在函数作用域中,再来分别用var/const/let三种方式定义的变量a---------*/

function add () {
	var a=2
	console.log(a)     
} 
add()                   //打印2
console.log(a)          //答案是Uncaught ReferenceError: a is not defined,因为var定义的变量遵循函数作用域的规则(所以外部不能访问函数内部的变量)
--------------------------------------------------------------------------
function add () {
	const a=2
	console.log(a)     
} 
add()                   //打印2
console.log(a)          //答案是Uncaught ReferenceError: a is not defined,因为const定义的变量遵循函数作用域的规则(所以外部不能访问函数内部的变量)
--------------------------------------------------------------------------
function add () {
	let a=2
	console.log(a)     
} 
add()                   //打印2
console.log(a)          //答案是Uncaught ReferenceError: a is not defined,因为let 定义的变量遵循函数作用域的规则(所以外部不能访问函数内部的变量)

我相信上面这个例子对于大家来说肯定是过于简单了,但是能快速帮助大家理解上述的定论,现在再来看一个经典面视题…

Demo2:

for (var i = 0; i < 5; i++) {
    setTimeout(function () {   
        console.log(i);       // 5 5 5 5 5 
    }, 300);
}
console.log(i)

for (let j = 0; j < 5; j++) {
    setTimeout(function () {
        console.log(j);       // 0 1 2 3 4
    }, 300);
}
console.log(i)

解析:为什么上面会是这样的结果呢?这里还涉及到了js的执行机制知识点,要两者结合才ok
第一个例子中用var 定义的i变量,在for(){}循环中属于块级作用域,但是var没有块级作用域一说,所以此时的i相当于是全局变量,整个循环的执行过程应该是这样的,首先定义了变量i,赋值为0,然后判断i是否小于5,成立走循环体内的代码,js执行遇到setTimeout语句时,因为它是宏任务,所以会将其放置到宏任务事件队列中,然后继续执行代码,i++,第一次循环结束,然后再次判断i是否小于5,又成立,再走循环内容,还是放到宏任务事件队列中,。。。以此类推,最终在宏任务事件队列中就有5个回调函数,但此时i已经变为了5,所以这5次打印都是5;
第二个例子中用let定义变量,这里我给你看张图你应该就明白了

在这里插入图片描述

这张图是通过babel打包后的代码原理,执行过程还是和第一个例子是相同的,一开始不执行函数,只是放到了事件队列中,但是会将每次循环的变量值都当成参数传给回调函数,所以最后回调函数执行时的变量j就是当时传过来的值,所以结果就是0,1,2,3,4了,这样你看明白了吗?

二、var

  1. 可重复定义
var a=1;
var a=2;
console.log(a)  //2
  1. 声明时可以不赋值
var a;
console.log(a) //undefined
  1. 声明提前
console.log(a)  //undefined
var a=10; 
console.log(a) //10

//上述代码相当于
var a;
console.log(a)  //undefined
a=10; 
console.log(a) //10
  1. 无法定义块级作用域变量,在块级作用域中定义相当于定义了一个全局变量
for(var a=0;a<10;a++){
	
}
console.log(a)  //10

三、const

  1. 当声明时不赋值报错
const a;     //不赋值会报错

在这里插入图片描述

  1. 改变const常量值时报错
const a=1;
a=2;

在这里插入图片描述

  1. 在同一作用域中重复定义报错
const a=1;
const a=2;

在这里插入图片描述

  1. 不会被声明提前(与var有区别)
console.log(a)
const a=2;

在这里插入图片描述

  1. 可以声明块级作用域的变量,块级作用域外无法访问内部变量!
if(true){
	const a=1;
}
console.log(a)

在这里插入图片描述

四、let

  1. 可以声明时不赋值
let a;
a=1;
console.log(a)
  1. 在同一作用域中不可以重复定义
let a;
let a=1;
console.log(a)

或者
let a=1;
var a=1;
console.log(a)

在这里插入图片描述

  1. 不会被声明提前(与var有区别)
console.log(a)
let a=1;

在这里插入图片描述

  1. 可以声明块级作用域的变量,块级作用域外无法访问内部变量!
if(true){
	let a=1;
}
console.log(a)

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ronychen’s blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值