每当我们运行代码的时候,代码就会生成执行上下文(可以理解为执行环境)
JavaScript执行环境主要分为三种:
JavaScript用栈处理多个执行上下文
作用域链
创建执行上下文分两个阶段
创建阶段
执行阶段
function books(){
var book = "书包里面的书本"
return function(){
console.log(book);
}
}
var bag = books();
bag()
上面代码的上下文创建顺序
全局执行上下文 = {作用域链:{全局变量对象}, {变量对象: books, bag}}
books执行上下文 = {作用域链:{books变量对象+全局变量对象},{变量对象:book}}
匿名函数执行上下文 = {作用域链:{匿名函数遍历对象+books变量对象+全局变量对象},{变量对象:}}
一道题:
for(var i = 0;i<5;i++){
setTimeout(function(){
console.log(i++);
},4000)
}
console.log(i);//556789
解析:
顺序是这样的,1. 循环走完 设置完一堆定时器 定时器里的函数并没有执行;2. 执行第6条的log输出第一个5;3. 定时器时间到,开始执行,此时i从5开始计算 输出 5,6,7,8,9;
没有使用闭包
let i = 0;
function fn(){
i++
console.log(i);
}
//另外一个程序
i= 1000
fn()//1001
我们希望i这个变量是私有的,脱离全局上下文环境
function count(){
let i = 0;
function fn(){
i++
console.log(i);
}
return fn
}
i = 1000
const fun = count()
fun()//1
这样子i就不在全局上下文环境中了,不会被全局上下文中的代码修改掉。
function count(){
let i = 0;
function fn(){
i++
console.log(i);
}
return fn
}
const fun = count()
此时:闭包引起了内存泄漏
不是所有的内存泄露都要手动回收的
比如react里面很多闭包不能回收的