闭包到底是什么呢?我觉得闭包是js独有的特性,需要延长一个变量的生命周期(延长作用域链的方式),使其在在外部也能访问内部的变量或函数,使得内部的变量或函数不会因离开了局部作用域而被销毁。
红宝书: 闭包,是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。
function outFunc(){
console.log("i am outside");
return function(){
return "i am inside";
}
}
要明白里面的细节,需要了解一下函数是怎么被调用的。
当某个函数被调用时,会创建一个执行环境及相应的作用域链。然后,使用arguments和其他命名参数的值来初始化函数的活动对象。但在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数的活动对象处于第三位,······直至作为作用域链终点的全局执行环境。
在函数的执行过程中,为读取和写入变量的值,就需要在作用域链中查找变量。
// arguments
function compare(value1,value2){
if(value1 < value2)
return -1;
}
var result = compare(1,2); // 这里在全局作用域中调用了他,调用compare就会创建一个arguments,value1,value2的活动对象。
全局执行环境的变量对象包含(result和compare)在compare()执行环境的作用域链中则处于第二位。(自己才是第一位,外面的开始是第二位...)
作用域链显然本质上是一个指向变量对象的指针列表,它只引用但不实际包含变量对象。
当函数执行完毕就会销毁自身活动对象,内存中仅保存全局作用域的变量对象。
在另一个函数内部定义的函数会将包含函数(即外部函数)的活动对象添加到它的作用域链中。(这里的重点是活动对象,包含外部函数的活动对象)。
举个🌰 在QuicFunc()函数内部定义的匿名函数的作用域链中,实际上将会包含外部函数QuicFunc()的 活动对象 。包含函数与内部匿名函数的作用域链。
var compare = QuicFunc("name");
var result = compare({name:"trans"},{name:"hi"});
function QuicFunc(name){
return function(Object1,Object2){
var value = Object1[name];
...
}
}
匿名函数被返回后,它的作用域链被初始化为包含QuicFunc()函数的活动对象和全局变量对象。这样匿名函数就可以访问QuicFunc()中定义的所有变量,QuicFunc()函数在执行完之后,其活动对象也不会被销毁,因为匿名函数的作用域链仍然引用这个活动对象。
匿名函数被销毁,QuicFunc()才会被销毁。
var compareNames = QuicFunc("name"); // 创建
var result = compareNames({},{}); // 调用
compareNames = null;// 销毁
函数可以作为参数被传递
函数可以作为返回值输出