作用域
在介绍let 和const 和 var 之前,我们先了解一下作用域,作用域在ES6之前,只用全局作用域和函数作用域,用var 声明的,在ES6 的时候,增加了以let 和const 声明的块级作用域
全局作用域
在全局作用域范围内可用,在页面关闭之后进行销毁
函数作用域
在函数内部定义 只在函数内部可以使用,在函数执行完毕之后进行销毁
块级作用域
块级作用域是ES6新增的,块级作用域是定义在大括号{}且只有let和const 声明的变量才是块级作用域在{}内使用
var let const 区别
1,var 存在变量提升(创建和初始化都提前了),let 和 const 提升了一部分(创建提升了),但是因为暂时性死区(变量没有初始化),不能在声明之前使用
2,var 可以在同一作用域重复声明变量,但是let 和 const 在同一作用域不能同时声明一个变量
3,var 只用全局作用域和函数作用域,const 和 let 多一个块级作用域
4,const声明的常量,定义的时候必须赋值,且声明之后不能修改,如果是复杂变量可以修改里面的属性值, var 和 let 可以先声明再赋值
全局下let和const 声明的变量不会作为window 对象的属性,单纯就是声明一个全局的块级变量,全局下var 声明的变量是作用域window对象属性的
变量提升的原理
js 引擎的工作方式是先解析代码,获取所有的变量,然后再运行,也就是,有预处理和执行两个阶段,var 声明的变量,在预处理的时候,会创建变量,并赋值为undefined,function 定义的函数,会将整个函数提升
var let const 练习题
这道题是我第一次面试时遇到的题,
var a =1
fun()
function fun(){
console.log(a)
if(!a){
var a=3
}
console.log(a)
}
console.log(a)
undefined,3,1 ,
这里考察的是变量提升,块级作用域以及函数作用域,块级作用域,var 声明的定义是没有块级作用域的概念的,所以在函数内第一行 a 存在变量提升,并为undefined,然后执行里面的代码,输出为3,但是这个是函数作用域,最后的a 打印的是1
a()
b()
var a=function(){return 1}
function b(){return 2}
a is not a function 2
这里考察的是var 声明的表达式函数和function声明的函数的区别,var声明的变量在提升的时候会赋值为undefined,而函数声明是直接将整个函数提升了
var a='aaa'
function fun(){
console.log(a)
if(false){
let a='bbb'
}
console.log(a)
}
fun()
aaa,aaa
var a='aaa'
function fun(){
console.log(a)
let a='bbb'
console.log(a)
}
fun()
Cannot access ‘a’ before initialization 这个地方是关于let 暂时性死区的问题
let a=2
console.log(window.a)
let b='lucy'
const c=b
b='windy'
console.log(c)
let d={name:'lucy'}
const e=d
d.name='windy'
console.log(e.name)
undefined lucy windy
a在全局定义的变量是不作用于window对象的,const 定义基础变量,一旦定义是不能被更改的,如果是复杂变量是可以改变属性值的
for 循环的作用域
对于let 来说,for(父作用域){子作用域},小括号和花括号的作用域是不同的,对于var 来说是没有区别的,因为var 没块级作用域
for循环的练习题
for(var a=0;a<3;a++){
let a='jjj'
console.log(a)
}
for (let a=0;a<3;a++){
var a='jjj'
console.log(a)
}
for(let i=0;i<3;i++){
let i='你好'
setTimeout(function(){console.log(i),1000})
}
for(var j=0;j<3;j++){
var j='bbb'
console.log(j)
}
jjj3 Identifier ‘a’ has already been declared 你好3 只有1个 bbb
对于let 父作用域和子作用域是互不影响的,对于var 来说是没有块级作用域的,所以第二个var 会影响 let ,let 在同一作用域下不能同时声明一个变量,所以会报错
for(var a=0;a<3;a++){
console.log(a)
setTimeout(function(){
console.log(a)
},0)
}
for (let a=0;a<3;a++){
console.log(a)
setTimeout(function(){
console.log(a)
},0)
}
0,1,2 3,3,3
0,1,2,0,1,2
这个涉及到js执行栈,setTimeout 是异步任务,所以会在for 循环执行完毕的时候再执行setTimeout ,var for 循环执行完之后,a 是3 ,所以setTimeout 会执行三个3
function fun(){
for(var a=0;a<5;a++){
console.log(a)
setTimeout(function(){
console.log(a)},0
)
}
for(var a=0;a<3;a++){
console.log(a)
setTimeout(function(){
console.log(a)},0
)
}
}
fun()
0,1,2,3,4
0,1,2
3,3,3,3,3
3,3,3
关于let const var 的分享就到此为止了,有兴趣的小伙伴可以留言谈论哦