var怎么实现 let
ES6之前,ES的作⽤域只有两种:全局作⽤域和函数作⽤域,是不⽀持块级作⽤域的

我们先解决这个问题,为什么要引⼊let和const?
作⽤域(scope)
作⽤域是指在程序中定义变量的区域,该位置决定了变量的⽣命周期。
作⽤域就是变量与函数 的可访问范围,即作⽤域控制着变量和函数的可⻅性和⽣命周期。
ES6之前,ES的作⽤域只有两种:全局作⽤域和函数作⽤域,是不⽀持块级作⽤域的
全局作⽤域中的对象在代码中的任何地⽅都能访问,其⽣命周期伴随着⻚⾯的⽣命周期。
函数作⽤域就是在函数内部定义的变量或者函数,并且定义的变量或者函数只能在函数内部被访问。函数 执⾏结束之后,函数内部定义的变量会被销毁。
JavaScript是如何⽀持块级作⽤域的
js
function foo(){
var a = 1
let b = 2
{
let b = 3
var c = 4
let d = 5
console.log(a)
console.log(b)
}
console.log(b)
console.log(c)
console.log(d)
}
foo()
第⼀步是编译并创建执⾏上下⽂

当进⼊函数的作⽤域块时,作⽤域块中通过let声明的变量,会被存放在词法环境的⼀个 单独的区域中,这个区域中的变量并不影响作⽤域块外⾯的变量,⽐如在作⽤域外⾯声明了变量b,在该作 ⽤域块内部也声明了变量b,当执⾏到作⽤域内部时,它们都是独⽴的存在。
在词法环境内部,维护了⼀个⼩型栈结构,栈底是函数最外层的变量,进⼊⼀个作⽤域块后,就会把 该作⽤域块内部的变量压到栈顶;
当作⽤域执⾏完成之后,该作⽤域的信息就会从栈顶弹出,这就是词法环 境的结构。
当执⾏到作⽤域块中的console.log(a)这⾏代码时,就需要在词法环境和变量环境中查找变 量a的值了
沿着词法环境的栈顶向下查询,如果在词法环境中的某个块中查找到了,就 直接返回给JavaScript引擎,如果没有查找到,那么继续在变量环境中查找。

var 怎么实现 let?
js
// 结果输出10 个 10, why?
for (var i = 0; i < 10; i++) {
setTimeout(function(){
console.log(i);
})
}
变量 i 是用 var 声明的,在全局范围内有效,所以全局中只有一个变量 i,当我们用 console.log(window.i) 来检验 i 时,发现 i 为10。每次循环时,setTimeout 定时器里面的 i 指的是全局变量 i ,而循环里的十个 setTimeout 是在循环结束后才执行,所以会输出十个 10
利用函数作用域修改为每个 i 为独立作用域
利用 函数作用域,在每次函数执行过程,中,都将当前的值,传入,每一个函数执行,内部都会声明一个新的参数作用域变量a,每个函数内部的 a 其实是不同的变量
js
for (var i = 1; i < 4; i++) {
(function f(a) {
setTimeout(function () {
console.log(a);
}, 1000);
})(i);
}