js预编译

我们都知道js执行遵循两个规则

1.函数声明整体提升

2.变量 声明提升

其实还有一点最重要的就是预编译,预编译往往发生在函数执行前,了解预编译,对我们理解函数执行非常关键。

预编译的前奏

1.imply global暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量就为全局属性所有。

2.一切声明的全局变量,全是window的属性。

下面就先看几个例子吧

例1 function fn(a){

  console.log(a);

  var a = 123;

       console.log(a);

  function a(){};

    console.log(a);

  var b = function(){};//这是函数表达式,不是函数声明(var b属于变量声明)

  console.log(b);

  function d(){}

}

fn(1);

1.创建AO对象

AO{

}

2.查找函数形参及函数内变量声明,形参名及变量名作为AO对象的属性,值为undefined 

AO{

  a:undefined;

  b : undefined;

}

3. 实参形参相统一,实参值赋给形参 (即把实参的值赋给形参,并不执行函数内的赋值)

AO{

  a:1;

  b : undefined;

}

4. 查找函数声明,函数名作为AO对象的属性,值为函数体

AO{ 

    a:function a(){};

  b : undefined;

  d : function d(){};

}

全部执行后

AO{ 

    a:123;

  b : function (){};

  d : function d(){};

}

函数执行结果

 function fn(a){

  console.log(a);  //function a(){}

  var a = 123;

       console.log(a); //123

  function a(){};

    console.log(a); //123

  var b = function(){};//这是函数表达式,不是函数声明(var b属于变量声明)

  console.log(b); // function (){};

  function d(){}

}

fn(1);

例2 function test(a,b){

  console.log(a);

  c = 0;

  var c;

  a = 3; 

  b = 2;

  console.log(b);

  function b(){};

  function d(){};

  console.log(b);

}

test(1);

1.创建AO对象

AO{

}

2.查找函数内的形参和变量声明,并将形参和变量声明作为AO对象的值,值为undefined

AO{

  a : undefined;

  b : undefined;

  c : undefined;

}

3.形参实参相统一,实参的值赋给形参

AO{

  a : 1;

  b : undefined;

  c : undefined;

}

4.查找函数声明,函数名为AO对象的属性,值为函数体

AO{

  a : 1;

  b : function b(){};

  c : undefined;

  d : function d(){}

}

全部执行后

AO{ 

    a:1->3;

  b : 2;

  c : 0;

  d : function d(){};

}

函数执行结果

 function test(a,b){

  console.log(a);//1

  c = 0;

  var c;

  a = 3; 

  b = 2;

  console.log(b);//2

  function b(){};

  function d(){};

  console.log(b);//2

}

test(1);

例3 function test(a,b){

  console.log(a);

  console.log(b);

  var b =234;

  console.log(b);

  a=123;

  console.log(a);

  function a(){};

  var a;

  b = 234;

  var b = function(){}

  console.log(a);

  console.log(b);

}

test(1);

1. 创建AO对象

AO{

}

2.查找函数形参和函数内的变量声明,形参名和函数名作为AO对象的属性,值为undefined

AO{

  a : undefined;

  b : undefined;

}

3.将形参和实参相统一,实参值赋给形参

AO{

  a : 1;

  b : undefined;

}

4. 查找函数声明,函数名作为AO对象的属性,值为函数体

AO{

  a : function a(){};

  b : undefined;

}

执行结果

 function test(a,b){

  console.log(a); //function a(){}

  console.log(b);//undefined

  var b =234;

  console.log(b);//234

  a=123;

  console.log(a);//123

  function a(){};

  var a;

  b = 234;

  var b = function(){}

  console.log(a);//123

  console.log(b);// function(){};

}

test(1);

预编译不只发生在函数里,还发生在全局里,这时候回身构成一个GO(Global Object //window Object)

例4

console.log(test);

function test(test){

  console.log(test);

  var test =234;

  console.log(test);

  function test(){

  }

}

test(1);

var test= 123;

1.先创建一个GO

GO{

}

2.查找全局的变量声明

GO{

  test : undefined;

}

4.查找函数声明

GO{

  test :  function test(test){

              console.log(test);

      var test =234;

      console.log(test);

      function test(){

        }

      }

    }

1.先创建一个AO

AO{

}

2.查找函数形参和函数内的变量声明,形参名和函数名作为AO对象的属性,值为undefined

AO{

  test : undefined;

}

3.将形参和实参相统一,实参值赋给形参

AO{

  test : 1;

}

4. 查找函数声明,函数名作为AO对象的属性,值为函数体

AO{

 test : function test(){

    };

}

例5

global = 100;

function fn(){

  console.log(global);

  global = 200;

  console.log(global);

  var global = 300;

}

fn();

var global;

1.GO{

  global : 100;

}

2.AO{

  global : undefined;

}

执行结果

global = 100;

function fn(){

  console.log(global);  //undefined

  global = 200;

  console.log(global); //200

  var global = 300; 

}

fn();

var global;

例6 

function test(){

  console.log(b);

    if(a){

   var  b  = 180;

  }

  c = 234;

  console.log(c)

}

var a;

test();

a = 10;

console.log(c);

1.GO{

  a : undefined;

  test :function test(){

      console.log(b);

        if(a){

       var  b  = 180;

         }

      c = 234;

      console.log(c)

      }

    }

2.AO{

  B:undefined;

}

执行结果

function test(){

  console.log(b); //undefined

  if(a){

   var b = 180;

  }

  c = 234;

  console.log(c); //234

}

var a;

test();

a = 10;

重要的事,说多少遍都不算多哈,最后总结:

预编译(函数执行前)※ 
1. 创建AO对象(Active Object -- 执行上下文) 
2. 查找函数形参及函数内变量声明,形参名及变量名作为AO对象的属性,值为undefined 
3. 实参形参相统一,实参值赋给形参 
4. 查找函数声明,函数名作为AO对象的属性,值为函数引用

预编译(脚本代码块script执行前) 
1. 查找全局变量声明(包括隐式全局变量声明,省略var声明),变量名作全局对象的属性,值为undefined 
3. 查找函数声明,函数名作为全局对象的属性,值为函数引用

原文地址:https://www.cnblogs.com/xuniannian/p/8081691.html