一、准备知识
1、预编译
函数在执行之前会有一个预编译环节,该环节用于检测是否存在语法错误,给对应的变量、函数赋值。
预编译环节:
- 创建AO对象(执行期上下文)
- 寻找声明的变量,值赋为
undefined
- 寻找形参和实参,实参的值赋给形参
- 寻找函数声明,值变成对应的函数
2、作用域
个人理解:作用域是函数的执行环境
3、作用域链
函数创建的AO对象组成的集合
二、闭包
含义:内部函数保存到外部
应用场景:缓存器
如何规避:使用立即执行函数
函数执行之后会销毁对应的AO对象,而如果在销毁之前把函数保存出来,那么它对应的AO对象不会消失
三、实例
function foo(){
var num = 100
function add(){
num ++
console.log('num : ' + num);
}
function decrease(){
num --
console.log('num : ' + num);
}
return [add,decrease]
}
var func = foo()
func[0]()//num : 101
func[1]()//num : 100
分析:
预编译过程
//foo:
GO:{
foo : function foo(){}
}
AO:{
num : 100
add : function add(){}
decrease : function decrease(){}
}
//add:
GO:{
foo : function foo(){}
}
AO:{
num : 100
add : function add(){}
decrease : function decrease(){}
}
//decrease:
GO:{
foo : function foo(){}
}
AO:{
num : 100
add : function add(){}
decrease : function decrease(){}
}
执行过程
//add先执行
num ++
//num = 101
foo 的 AO: num = 101
由于函数add和函数decrease都在函数foo的内部,而且自身的AO没有值,修改的实际上是foo的AO
//decrease后执行
num --
//num = 100
foo 的 AO: num = 100