js的高级知识 —— 词法分析

一、词法分析方法

js运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤:

  • 分析参数
  • 再分析变量的声明
  • 分析函数说明

二、具体步骤

函数在运行的瞬间,生成一个活动对象(Active Object),简称AO
1.分析参数

  • 函数接收形式参数,添加到AO的属性,并且这个时候值为undefined,即AO.age=undefined
  • 接收实参,添加到AO的属性,覆盖之前的undefined

2.分析变量声明:如var age;或var age=23;

  • 如果上一步分析参数中AO还没有age属性,则添加AO属性为undefined,即AO.age=undefined
  • 如果AO上面已经有age属性了,则不作任何修改

3.分析函数的声明,如果有function name(){}把函数赋给AO.name ,覆盖上一步分析的值

例子1:

function t1(age) {
  console.log(age);
  var age = 27;
  console.log(age);
  function age() {}
  console.log(age);
}
t1(3);

词法分析阶段:

首先形成Active Object即AO对象
分析形式参数
  • AO.age = undefined
  • 传入实参即对AO.age=undefined进行覆盖:AO.age = 3
分析局部变量
  • 存在var age = 27;
  • 这个时候遵循如果AO.age存在值则不作任何修改,按照第一步分析的最后结果AO.age = 3,所以这里不作任何修改即:AO.age = 3
分析函数的声明
  • 因为函数中存在function age(){}函数
    所以按照规则应该将函数赋值给AO.age覆盖第二步分析的AO.age = 3即: AO.age = function age(){}
执行阶段
  • 执行t1函数,到console.log(age)时,词法分析的最后AO.age= function age(){},所以会打印:
    function age(){}
  • var age=27;给age赋值27,到第二个console.log(age)这个时候age已经重新被赋值27,所以这个时候会打印:27
  • function age() 并没有调用所以并不会执行
    到第三个console.log(age)这个时候age的值并没有被再次修改,所以这个时候会打印:27
    运行js查看结果如下与我们分析的完全相符:
    image.png

例子2:

function t1(age) {
  var age;
  console.log(age);
  age = 23;
  console.log(age);
  function age() {
    console.log(age);
  }
  age();
  console.log(age);
}
t1(22);

词法分析阶段:

首先形成Active Object即AO对象
分析形式参数
  • AO.age = undefined
  • 传入实参即对AO.age=undefined进行覆盖:AO.age = 22
分析局部变量
  • 这个时候遵循如果AO.age存在值则不作任何修改,所以这里不作任何修改即:AO.age = 22
分析函数的声明
  • 因为函数中存在function age(){}函数
    所以按照规则应该将函数赋值给AO.age覆盖第二步分析的AO.age = 22即: AO.age = function age(){}
执行阶段
  • 执行t1函数,到console.log(age)时,词法分析的最后AO.age= function age(){},所以会打印:
    function age(){}
  • age = 23,这个时候会覆盖原来的function age(){console.log(age)},所以第二个console.log(age)会打印:23
  • function age() 并没有调用所以并不会执行
    age() 这个时候的age还是23,并不是函数表达式,所以这里会报错
    运行js查看结果如下与我们分析的完全相符:


    image.png

三、补充说明,函数声明与函数表达式

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

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

a在词法分析时,就发挥作用;
b只有在执行阶段,才发挥作用。

词法作用域
所谓词法作用域是说,其作用域为在定义时(词法分析时)就确定下来的,而并非在执行时确定。白话就是在函数未执行前,函数执行的顺序已经被确定,而不是类似JAVA一样,是在执行前根本不知道执行顺序。

你可能感兴趣的:(js的高级知识 —— 词法分析)