JavaScript-变量提高(AO、GO)编译、闭包

JavaScript是一个解释型语言

MDN上明确的说,JavaScript是一个轻量级的、解释型的、面向对象的、将函数视为一级公民的语言。
那么,既然js是一个解释型语言,那它就是在运行时把代码转换成机器能够识别的语言。哪它又为何会存在变量提高呢?
下面这篇文章给出了解释,在此也特别感谢做者的分享!
https://mp.weixin.qq.com/s/ne...数组

变量提高、预编译过程

function fn(c){
    console.log(c);  //true
    var c = false;
    console.log(a);  //function a(){}
    var a = 1;
    console.log(a);  //1
    function a(){
        
    };
    console.log(a);  //1
    b();             //函数声明
    var b = function(){
        console.log("函数表达式");
    }
    function b(){    
        console.log( "函数声明" )
    }
    b();             //函数表达式
    var d = 4;
}
fn(true);

上面这个fn方法很简单,相信不少人都能过作出来,但确定也不少人不理解结果为何是这样!
那么这个过程是怎样执行的呢:
首先,js在执行前会产生一个GO(Global Object),也就是咱们常说的全局做用域。当一个方法被调用的时候会造成一个局部做用域AO(Activation Object)。
全局代码在执行的时候,先是变量提高,在全局做用域内添加属性,而后是函数(以函数声明建立的函数)提高,再是代码执行。
函数在被调用的时候,以上面的fn这个方法为例,进入函数上下文,可是在执行代码以前,经历的阶段:
第一阶段:首先建立一个AO,并包含下列属性:闭包

AO : {
    arguments: <ArgO>,  //函数内部参数的类数组对象
    c: true,            //传入的参数,若是没有传递实参,那么值就是undefined
}

第二阶段:函数内部的函数(以函数声明建立的函数)提高函数

AO : {
    arguments: <ArgO>,
    c: true,
    a: function a(){},
    b: function b(){ console.log( "函数声明" ) }
}

第三阶段:函数内部的变量提高code

AO : {
    arguments: <ArgO>,
    c: true,
    a: function a(){},
    b: function b(){ console.log( "函数声明" ) },
    d: undefined
}

函数内部又定义了变量 var c和var a,当变量提高时,发现AO中已经存在a和c属性,若是变量名称跟已经声明的形参或函数相同,则变量声明不会干扰已经存在的这类属性。若是不相同切不存在,那就会放到AO中,值为undefined。对象

当上面的这些准备工做作完以后,才会开始执行函数内部的代码,这样就很好明白,函数内部的变量,在什么阶段分别表明什么样的值!ip

闭包解析

在JavaScript高级程序3中,对闭包的描述是这样的,闭包是指有权访问另外一个函数做用域中的变量的函数。那么,很显然,闭包其实就是一个函数。
那么咱们怎样经过GO、AO理解闭包呢:作用域

function foo(){
    var a = 1;
    function fnSon(){
        a++;
        console.log(a);
    }
    return fnSon;
}
var fnTest = foo();
fnTest();   //2
fnTest();   //3

当foo这个方法被调用的时候,建立一个AO,当函数执行完以后AO里面包含了变量a、函数fnSonget

AO:{
    a:1,
    fnSon: function(){}
}

此时的fnSon被赋值给了fnTest,那么foo方法的AO在执行完以后就没办法被销毁,当fnTest被调用的时候,代码执行完以后,foo的AO对象中的a变成了2,再次调用fnTest的时候就变成3。io

相关文章
相关标签/搜索