javascript 预解析

所谓预解析,既是函数执行的前一刻,js需要做的事情,函数的预解析分四步:

一、创建AO对象

二、寻找函数中的形参及变量声明,并把形参和变量的名作为AO对象的属性名,值为undefined

三、实参、形参相统一

四、寻找函数中的函数声明,并把函数名作为AO对象的属性名,函数整体赋值给该属性名,如果函数名与变量名重复,则把函数体直接赋值给变量

 

注意,以上为函数的预解析,如果是全局下执行某段js代码,它的预解析步骤与函数预解析步骤基本一致,差别有两点:

一、全局作用域下,创建的不是AO对象,是GO对象

二、全局作用域下,没有了第三步:实参、形参相统一

 

测试题:

function fn(a){
  console.log(a);
  var a = 123;
  console.log(a);
  function a(){}
  console.log(a);
  var b = function(){}
  console.log(b);
  function d(){}            
}

fn(1);

 

函数执行前 执行预解析

第一步:创建AO对象

 AO {}

 

第二步:寻找函数中的形参及变量声明,并把形参和变量的名作为AO对象的属性名,值为undefined

AO {
  a:undefined,
  b: undefined    
}

  注:形参和变量重名时,只写一个即可,即:写一个a即可

 

第三步:实参、形参相统一

AO {
  a:1,
  b: undefined    
}

 

第四步:寻找函数中的函数声明,并把函数名作为AO对象的属性名,函数整体赋值给该属性名,如果函数名与变量名重复,则把函数体直接赋值给变量

AO{
  a:function(){},
  b:undefined,
  d:function(){}  
}

  

至此,js的预解析执行完毕,开始逐行执行代码

 

第一行:console.log(a);    js到AO对象里找 a   所以  打印 function(){}

第二行:var a = 123;       因为预解析时 var a已被提升,所以这一行只是给a赋值,此刻AO对象里的a变为123;

AO{
  a:123,
  b:undefined,
  d:function(){}  
}

第三行:console.log(a);   js到AO对象里找a  所以打印 123;

第四行:function a(){}     预解析时已提升,所以 忽略

第五行:console.log(a);   js到AO对象里找a  所以打印 123;

第六行:var b = function(){}  因为预解析时 var b已被提升,所以这一行只是给b赋值,此刻AO对象里的b变为function(){};

AO{
  a:123,
  b:function(){},
  d:function(){}  
}

第七行:console.log(b);  js到AO对象里找b  所以打印 function(){};

第八行:function d(){}  预解析时已提升,所以忽略

函数执行完毕!

 

posted @ 2018-11-15 10:10  雅士伊人  阅读(252)  评论(0编辑  收藏  举报