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

2023年6月28日08:09:59

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)

  • 作者:北极来的码农
  • 原文链接:https://blog.csdn.net/qq_38311283/article/details/83346784
    更新时间:2023年6月28日08:09:59 ,共 1933 字。