【JavaScript】闭包和作用域链

发布于 2017-04-27  281 次阅读


定义函数的方式有两种
1、函数声明(函数声明提升,执行代码之前会先读取函数声明)
Function obj1(){
//函数体
}
2、函数表达式
Var obj2 = function(){
//函数体
}

两者之间的区别:函数提升的关键,很重要!
//正确的
sayHi();
function sayHi(){
alert("Hi!");
}
//错误,使用前必须先赋值
sayHi();
Var sayHi = function (){
alert("Hi!");
}

递归函数:在一个函数通过调用自身的情况下构成
使用arguments.callee来实现对函数的递归调用,它是一个指向正在执行的函数的指针

闭包
定义:有权访问另一个函数作用域中的变量的函数

作用域链
当某个函数被调用时,会创建一个执行环境以及相应的作用域链(用来保证对执行环境
有权访问的所有变量和函数的有序访问)

每个执行环境都有一个与之关联的变量对象(如果环境是函数,则其活动对象=变量对象)
使用arguments和其他命名参数来初始化函数的活动对象(活动对象最开始只包含arguments这一个变量,它在全局环境是不存在的)

作用域链中前端是当前执行代码所在环境的变量对象
下一个对象来自包含(外部)环境
再下一个变量对象来自下一个包含环境
一直延伸到全局执行环境(最后一个对象)

作用域链本质上是一个指向变量对象的指针列表,它只引用但不实际包含变量对象
当函数执行完毕后,局部活动对象被销毁(闭包除外),内存中只保存全局作用域
闭包的作用域链
在另一个函数内部定义的函数(通常是匿名函数)会将包含函数(外部函数)的活动对象添加到它的作用域链中
外部函数执行完毕后,作用域链会被销毁,但它的活动对象依然会保留在内容中
除非接触对匿名函数的引用(释放内存)

闭包的副作用
闭包只能取得“外部”函数中任何变量的最后一个值
闭包所保存的是整个变量对象,而不是某个特殊的变量
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(){
return i;
};
}
return result;
}
createFunctions()函数的活动对象引用的都是同一个变量i
解决办法
创建另一个匿名函数强制让闭包的行为符合预期
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(num){
return function(){
return num;
};
}(i);
}
return result;
}