• 深入JavaScript:词法分析、连续赋值猜想


    JavaScript:词法分析、连续赋值猜想

    原创文章,转摘请注明出处:苏福:http://www.cnblogs.com/susufufu/p/5851642.html

    深夜发文,先吐槽下博客园的编辑器,真不方便!我都是本地编辑好了在粘过来的,要是不用MarkDown写的话,那每次都得改改改啊!

    先说下这个老话题:连续赋值
    例1:

    function a(){
        var o1 = o2 = 5;
    }
    a();
    console.log(o1);
    console.log(o2);
    

    结果是什么?console.log(o1);这句简单undefined,而console.log(o2);这句呢?答案是5,o2变成了全局变量了
    这是实际执行顺序:

    var o1;
    o2 = 5; //o2未使用var声明,所以变全局变量了
    o1 = o2;
    

    例2:

    var foo = {n:1};
    var bar = foo;
    foo.x = foo = {n:2};
    console.log(foo.x); 
    console.log(bar.x); 
    

    很早以前的面试题目了,相信很多人知道答案,考点:词法分析、执行顺序、运算符优先级等
    这是我理解的实际执行顺序:

    var foo;
    var bar;
    foo = {n:1};
    bar = foo; //bar = {n:1}
    foo.x = undefined; //
    foo.x = (foo = {n:2});
    console.log(foo.x); //undefined
    console.log(bar.x); //{ n: 2 }
    

    我是这么猜想的:自我感觉勉强说的通,有不对的地方请指出!
    JS引擎遇foo.x = foo = {n:2}; 词法分析为foo.x, =, foo, =, {n:2}
    执行顺序:
    1. 先为foo添加x属性,未赋值(undefined),这里的foo还是{n:1}
    2. 遇到第一个'=',准备为x赋值
    3. '='优先级最低,先计算右边表达式的值
    4. 执行foo = {n:1},并将结果赋值给x
    最终foo的引用指向了{n:2}
    而bar的引用没变,始终指向原来的{n:1},而{n:1}被添加了x属性{n:2}变为{n:1,x:{n:2}},这就是最后bar引用的值

    下面给大家介绍下JS的词法分析,参考自《javascript权威指南》《你不知道的javascript》

    JavaScript代码自上而下执行,但是在js代码执行前,会首先进行词法分析,所以事实上,js运行要分为词法分析和执行两个阶段。

    词法分析

    词法分析主要分为3步:
    第1步:分析形参
    第2步:分析变量声明
    第3步:分析函数声明
    如果存在函数嵌套,则从外往内进行词法分析

    具体步骤:

    1. 在函数执行的一瞬间,产生一个空的 Active Object(活动对象),下面简称AO
    2. AO对象初始化
      2.1 函数声明的形参,形成AO的属性,默认值是undefined,
      2.2 接收实参,给刚刚形成AO的属性的形参赋值
    3. var声明、函数声明均被提升到函数体顶部(若var声明、函数声明同名,则函数声明将覆盖变量声明),注意,var声明只提前了声明部分,而函数声明提前了整个函数定义。
    4. 分析var声明变量!如 var age;(变量的值是在运行时期决定)
      4.1 如果AO上没有age属性,则给AO添加age属性,默认值是undefined
      4.2 如果AO上有age属性,则不做任何操作。
    5. 分析函数声明!如 function foot(){}
      51 如果AO上没有foot属性,则把函数赋给AO.foot属性
      5.2 如果AO上有foot属性,则会直接覆盖,把函数赋给AO.foot属性(因为:若var声明、函数声明同名,则函数声明将覆盖变量声明)
    6. 依据此时AO的值,自上而下执行代码

    代码演示与分析:

      function a(b){
           alert(b);
           function b(){
               alert(b);
           }
           b();
       }
       a(1);
    

    这是个常见的面试题,如果不懂JavaScript的词法分析,根本看不懂,下面就按照JavaScript的词法步骤进行分析,前面说过JavaScript自上而下执行,但是先进行词法分析后执行代码

    分析过程:

    1. 形成活动对象AO={}
    2. 分析形参,--> AO={b:undefined}; 分析传参,--> AO={b:1}
    3. 分析变量声明var,没有
    4. 分析函数声明,AO.b=function(){alert(b);},执行覆盖操作

    执行过程:
    alert(b);//function
    b(); // 执行function b...alert(b),在函数b的作用域内部找不到b,根据作用域链原理往外层寻找,找到b就是函数自己,打印出function ...

  • 相关阅读:
    Components controls 区别
    lazarus 2016 2月18 4:22:35 支持android开发了, 既ios,linux,macosx,window,web 后 囊括一切啦。 哈哈
    Delphi MlSkin V1.1 发布啦! 它能让你的程序拥有像QQ一样多彩炫丽的外观!
    Tclientdataset的CloneCursor问题 clientdataset 复制 赋值 的问题
    字符串 映射 函数
    字符串 映射相应的 函数 字符串驱动技术—— MethodAddress , MethodName , ObjectInvoke
    一分钟了解nohup和&的功效
    Linux shell标准输入,标准输出,错误输出
    (一)shell编程之执行脚本的三种方式
    Shell:执行脚本文件方法
  • 原文地址:https://www.cnblogs.com/susufufu/p/5851642.html
Copyright © 2020-2023  润新知