var、function、let、const 的区别及变量提升

首页 / 新闻资讯 / 正文

JS的解析器会做两部分的工作: 
1)预解析 | 预解析仓库 = “找东西“(找VAR , FUNCTION 以及参数) 
2)逐行解读代码

预解析时,var 、function 会发生我们通常所说的变量提升

// 变量提升 var function console.log(a) // a() { //   console.log('this is a2') // }  var b=3 a() console.log(a) var a = 1 function a() {   console.log('this is a1') } console.log(a)// 1 function a(a, b) {   console.log('this is a2')   console.log(a)   console.log(b) } console.log(a)// 1 var a = 2 console.log(a)// 2   log: /** ƒ a(a, b) {   console.log('this is a2')   console.log(a)   console.log(b) } this is a2 undefined undefined ƒ a(a, b) {   console.log('this is a2')   console.log(a)   console.log(b) } 1 1 2 {a: 3}  */  /**  * 预解析步骤:  * 1.首先解析到第七行var a, 在预解析器中定义 a =undefined  * 2.解析到a1, 将解析器中 a = a() {       console.log('this is a1')     }     3.解析到a2, 将解析器中 a = a() {       console.log('this is a2')     }     4.解析到var a= 2,由于a =undefined, 所以a = a() {       console.log('this is a2')     }  */

预解析步骤:

1.首先解析到第七行var a, 在预解析器中定义 a =undefined

2.解析到a1, 将解析器中 a = a() {

console.log('this is a1')

}

3.解析到a2, 将解析器中 a = a() {

console.log('this is a2')

}

4.解析到var a= 2,由于a =undefined, 所以a = a() {

console.log('this is a2')

}

 

// 一是不存在变量提升:

 

// 二是let声明的变量不能重复声明,否则会报错

 

// var i = 1;

// var i = 2;

// console.log(i)//2

// let i = 1;

// let i = 2;

// console.log(i)//报错

 

// 三是新增了块级作用域。

 

for(var i = 0; i < 5; i++){

}

console.log(i) // 5

for(let i = 0; i < 5; i++){ // 这个i只能在这个for循环内使用

}

console.log(i) // 报错:i is not defined

// 一个常见的闭包问题就可以用let来解决。

 

// for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域

for (let i = 0; i < 3; i++) {

let i = 'abc';

console.log(i);

}

// abc

// abc

// abc

// 上面代码正确运行,输出了 3 次abc。这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。

 

for(var i = 0; i < 5; i++){

setTimeout(function(){

console.log(i)

}, 1000)

}

// 这个可谓是经典的闭包题了,结果是一次性输出5个5。如何让它输出01234呢,ES5我们用IIFE来解决。

 

for(var i = 0; i < 5; i++){

(function(e){

setTimeout(function(){

console.log(e)

}, 1000)

})(i)

}

// 将代码放在一个IIFE中创建了一个独立的作用域,传入i,这样就实现了对i的暂存。(详细可参看我的另一篇关于闭包的文章。)

// ES6就可以用let来解决了。

 

for(let i = 0; i < 5; i++){

setTimeout(function(){

console.log(i)

}, 1000)

}

// 其实JS引擎解析上述代码中的let,就是按照ES5的规范来解析的。即创建一个IIFE传入i.

// console.log(b)

// let b = 2

// for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域

for (let i = 0; i < 3; i++) {

let i = 'abc';

console.log(i);

}

// abc

// abc

// abc

// 上面代码正确运行,输出了 3 次abc。这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。

 

const c = {}

c.a=3

console.log(c)