闭包是指有权访问另一个函数作用域中的变量的函数。
- 如何创建作用域链(粗略)- 函数被调用,会创建一个执行环境和作用域链
- arguments和其他命名参数的值来初始化函数的活动对象(活动对象作为变量对象)
- 作用链中外部函数依次往外排
 
- 作用域链的作用- 函数执行过程中,为读取和写入变量的值,需要在作用域链中逐级查找变量。
 
| 1 | 例子 | 
例子如图
- 如何创建作用域链(详细)- 全局环境的变量对象始终存在,而函数的局部环境的变量对象,则只在函数执行的过程中存在。- 在创建函数时,会创建一个预先包含全局变量对象的作用域链,并保存在函数内部的[[Scope]]属性中。
- 在调用函数时,会为函数创建一个执行环境,然后通过复制函数的[[Scope]]属性中的对象构建起执行环境的作用域链。
- 函数的活动对象(在这被当作变量对象)被创建并被推入执行环境作用域的前端。
 
- 作用域链本质上是一个指向变量对象的指针列表,它只引用但不实际包含对象
 
- 全局环境的变量对象始终存在,而函数的局部环境的变量对象,则只在函数执行的过程中存在。
- 常见的闭包方式:在一个函数内部创建另一个函数,如下1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11function createComparisonFunction(propertyName){ 
 return function(object1,object2){
 var value1=object1[propertyName];
 var value2=object2[propertyName];
 if.....
 }
 }
 var compare=createComparsionFunction("name");
 var result=compare({name:"Nicholas"},{name:"Greg"});
 即使内部的匿名函数被返回了,且在其他地方被调用,仍可以访问变量propertyName.
作用域链的关系如图
1.闭包与变量
闭包的问题:闭包只能取得包含函数中任何变量的最后一个值。
| 1 | function createFunctions(){ | 
- 解释:- 每个函数作用域链中保存着包含函数的活动对象,则都是引用同一个变量i;
- 包含函数返回后,变量i值是10,此时每个函数都引用着保存着变量i的包含函数活动对象
- 每个函数内部i的值都是10。
 
| 1 | 改进后的闭包 | 
- 解释:- 没有直接把闭包赋值给数组,而是定义了一个匿名函数,并将立即执行该匿名函数的结果赋值给数组。
- 在匿名函数内部,创建并返回一个访问num的闭包。
- 闭包只能取得包含函数任何变量的最后一个值。
 
2.this对象
- this对象是在运行时基于函数的执行环境绑定的:在全局函数中,- this等于window,而当函数被作为对象的方法调用时,- this等于那个对象。(非闭包,匿名函数情况下)
- 匿名函数的执行环境具有全局性,因此其this对象通常指向window(除 - call()和- apply()改变执行环境外)。- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- var name="The window"; 
 var object={
 name:"My object",
 getNameFunc:function(){
 return function(){
 return this.name;
 };
 }
 };
 alert(object.getNameFunc()()); //"The window"(非严格模式下)
- 解释: - 每个函数在被调用时都会自动取得两个特殊变量(对象):this和arguments。
- 内部函数在搜索这两个变量时,只会搜索到其活动对象为止,永远不会直接访问外部函数中的这两个变量。所以当搜不到时就等于window。
- but可以间接访问.把外部作用域中的this对象保存在一个闭包能够访问的变量中,就可以让闭包访问对象了。
 
- 每个函数在被调用时都会自动取得两个特殊变量(对象):
| 1 | var name="The window"; | 
- 几种特殊的情况1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11var name="The window"; 
 var object={
 name:"My object",
 getName:function(){
 return this.name;
 }
 };
 object.getName(); //"My object"
 (object.getName)() //"My object"
 (object.getName=object.getName)() //"The window" 在非严格模式下。赋值的是函数本身,this的值不能得到维持,相当于在全局环境下调用,所以指向"window"。
3.内存泄漏
IE早些版本的问题
