js 词法剖析,词法作用域

先来看个罕见的面试题以下:

var a = 10;
function test(){
    alert(a);  //undefined
    var a = 20;
    alert(a); //20
}
test();

疑问:为何呢?test()实行时,虽然a=20没有赋值,然则父级作用域里是有a=10的,不该该是undefined呀,js是按递次实行的,此时的var num = 20;基础没有实行,所以应该是10!!你是否是也是这么以为的,就和我当初一样???

剖析:尽人皆知,js代码是自上而下实行的,JavaScript并非传统的块级作用域,而是函数作用域。JavaScript引擎会在代码实行前举行词法剖析,所以事实上,js运转分为此法剖析和实行两个阶段。

JavaScript代码运转前有一个相似编译的历程即词法剖析,词法剖析主要有三个步骤:

  • 剖析参数

  • 再剖析变量的声明

  • 剖析函数声明

具体步骤以下:

函数在运转的霎时,天生一个运动对象(Active Object),简称AO

第一步:剖析参数:

  1. 函数吸收形式参数,增加到AO的属性,而且这个时刻值为undefined,即AO.name=undefined

  2. 吸收实参,增加到AO的属性,掩盖之前的undefined

第二步:剖析变量声明:如var name;或var name=’mary’;

  1. 假如上一步剖析参数中AO还没有name属性,则增加AO属性为undefined,即AO.name=undefined

  2. 假如AO上面已有name属性了,则不作任何修正

第三步:剖析函数的声明:

假如有function name(){}把函数赋给AO.name ,掩盖上一步剖析的值

剖析下面这个栗子:

1.var a = 10;
2.function test(a){
3.    alert(a);           //function a (){}
4.    var a = 20;
5.    alert(a);           //20
6.    function a (){}
7.    alert(a);           //20
8.    }
9.
10.test(100);

词法剖析:

第一步,剖析函数参数:

 形式参数:AO.a = undefined
 吸收实参:AO.a = 100

第二步,剖析局部变量:

第4行代码有var a,然则此时已有AO.a = 100,所以不做任何修正,即AO.a = 100

第三步,剖析函数声明:

第6行代码有函数a,则将function a(){}赋给AO.a,即AO.a = function a(){}

实行代码时:

第3行代码运转时拿到的a时词法剖析后的AO.a,即AO.a = function a(){};
第4行代码:将20赋值给a,此时a=20;
第5行代码运转时a已被赋值为20,效果20;
第6行代码是一个函数表达式,所以不做任何操纵;
第7行代码运转时还是20;

ps:

1.var a = 10;
2.function test(a){
3.    var a;               //证实词法剖析第二步。
4.    alert(a);           //100
5.    a = 20;
6.    alert(a);           //20
7.}
7.test(100);

ps:

var a = 10;
function test(a){
    alert(a);         //100
    var a = 20;
    alert(a);         //20
    a = function(){}        //是赋值,只要在实行时才有用
    alert(a);         //function(){}
}
test(100);

ps:(实行效果同上)

var a = 10;
function test(a){
    alert(a);                //100
    var a = 20;
    alert(a);                //20
    var a = function(){}        //是赋值,只要在实行时才有用
    alert(a);                //function(){}
}
test(100);

补充申明:函数声明与函数表达式

//函数声明
function a(){
}
//函数表达式
var b = function(){
}

a和b在词法剖析时,区分:

a在词法剖析时,就发挥作用;
b只要在实行阶段,才发挥作用。

词法作用域

所谓词法作用域是说,其作用域为在定义时(词法剖析时)就肯定下来的,而并非在实行时肯定。白话就是在函数未实行前,函数实行的递次已被肯定,而不是相似JAVA一样,是在实行前基础不知道实行递次。

    原文作者:Mary
    原文地址: https://segmentfault.com/a/1190000010187653
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞