JS之闭包(预编译=>执行期上下文=>作用域及作用域链=>闭包=>立即执行)

318 阅读2分钟

预编译:

生成全局及函数内部的执行期上下文

执行期上下文==>以函数为例:(全局执行期上下文(GO)的创建类似)

(1)在开始执行的前一刻,创建AO(activation object);

(2)将形参和声明的变量放入OA,值为undefined;

(3)将实参和形参统一;

(4)在函数体里找到函数声明,值赋予函数体。

(5)在执行相应赋值语句时,修改声明的变量。

需要注意:函数表达式,如“var test=function(){}”,不能视为函数声明。

作用域及作用域链:

(1)作用域的概念:每个函数都是一个对象(如何理解?),对象中有些属性可以访问,有些属性不能访问,由JavaScript引擎存取。[[scope]]就是其中一个,即作用域,内部存储了执行期上下文的集合。

(2)作用域链:由作用域的概念引出,因为作用域内部的执行期上下文是呈链式连接的,所以又称作作用域链。链的由上到下分布对应由内到外的执行期上下文。---------在函数被定义时,作用域链就饱含了上层的执行期上下文,在执行时将自己的执行期上下文加入作用域链。

闭包:

(1)外在表现: 在函数运行结束前,把其内部的函数体拿出,就形成了闭包。

(2)意义: 外部函数在执行结束后,其执行期上下文销毁,但是因为内部函数的作用域链包含了外部函数的执行期上下文,导致外部函数的执行期上下文随着内部函数的移出被保存了下来。

(3)栗子:

function test(){
    var count=1;
    function add(){
        count++;
        console.log(count);
    }
    return add();
}
var counter=test();
counter();
counter();
counter();
counter();
.
.
.

add()移出后保存了test的AO,因此每次执行后AO内的count值都会被修改。又因为是test 的AO,此时count只能由counter调用,全局无法访问。

立即执行:

(1)目的:针对初始化功能的函数,执行完立即释放。

(2)语法形式:表达式+执行符号。

(1) (function test(){})();
(2) (function text(){}());