资讯专栏INFORMATION COLUMN

js 词法分析,词法作用域

2450184176 / 1930人阅读

摘要:引擎会在代码执行前进行词法分析,所以事实上,运行分为此法分析和执行两个阶段。词法作用域所谓词法作用域是说,其作用域为在定义时词法分析时就确定下来的,而并非在执行时确定。

先来看个常见的面试题如下:

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

第一步:分析参数:

函数接收形式参数,添加到AO的属性,并且这个时候值为undefined,即AO.name=undefined

接收实参,添加到AO的属性,覆盖之前的undefined

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

如果上一步分析参数中AO还没有name属性,则添加AO属性为undefined,即AO.name=undefined

如果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一样,是在执行前根本不知道执行顺序。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/83976.html

相关文章

  • js 词法分析词法作用

    摘要:引擎会在代码执行前进行词法分析,所以事实上,运行分为此法分析和执行两个阶段。词法作用域所谓词法作用域是说,其作用域为在定义时词法分析时就确定下来的,而并非在执行时确定。 先来看个常见的面试题如下: var a = 10; function test(){ alert(a); //undefined var a = 20; alert(a); //20 } te...

    CrazyCodes 评论0 收藏0
  • 深入贯彻闭包思想,全面理解JS闭包形成过程

    摘要:下面我们就罗列闭包的几个常见问题,从回答问题的角度来理解和定义你们心中的闭包。函数可以通过作用域链相互关联起来,函数内部的变量可以保存在其他函数作用域内,这种特性在计算机科学文献中称为闭包。 写这篇文章之前,我对闭包的概念及原理模糊不清,一直以来都是以通俗的外层函数包裹内层....来欺骗自己。并没有说这种说法的对与错,我只是不想拥有从众心理或者也可以说如果我们说出更好更低层的东西,逼格...

    snowell 评论0 收藏0
  • You-Dont-Know-JS - 词法作用

    摘要:原文原文原文词法作用域作用域有两种常见的模型,一种叫做词法作用域,一种叫做动态作用域。其中词法作用域更常见,被大多数语言采用,包括。值得注意的是,一个函数作用域只有可能存在于一个父级作用域中,不会同时存在两个父级作用域。 原文: 原文1 | 原文2 Lexical Scope - 词法作用域 作用域有两种常见的模型,一种叫做 词法作用域 Lexical Scope,一种叫做...

    bang590 评论0 收藏0
  • 重读你不知道的JS (上) 第一节二章

    摘要:词法作用域定义在词法阶段的作用域由你在写代码时将变量和块作用域写在哪来决定的,因此当词法分析器处理代码时会保持作用域不变。欺骗词法作用域在词法分析器处理过后依然可以修改作用域。 你不知道的JS(上卷)笔记 你不知道的 JavaScript JavaScript 既是一门充满吸引力、简单易用的语言,又是一门具有许多复杂微妙技术的语言,即使是经验丰富的 JavaScript 开发者,如果没...

    baihe 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<