JavaScript预编译和变量提升

JavaScript是解释型语言,会先预编译,然后执行,在执行过程中顺序执行。
因此在JS中存在变量提升的现象

在函数中预编译执行步骤:

  • 创建空AO对象,(Activity Object)执行期上下文
  • 寻找函数的形参变量声明,将变量和形参作为AO对象的属性名,值为undefined
  • 将形参和实参相统一,将undefined更改为具体实参值。
  • 寻找函数中的函数声明,将函数名作为AO属性名,值为函数体
  • 预编译环节结束
  • 执行,不断更新AO对象
  • 执行完毕,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(){}
}
  1. 创建空AO对象
AO{
  // 空对象
}
  1. 寻找函数形参和变量声明
AO{
  a: undefined,
  b: undefined,
}
  1. 将形参和实参相统一
AO{
  a: 1,
  b: undefined
}
  1. 函数声明
AO{
  a: function a(){},
  b: undefined,
  d: function d(){},
}

预编译环节结束,AO对象更新为

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

函数开始顺序执行

function fn(a){
  console.log(a); // function a(){}
  var a = 123     // 对a赋值,AO对象改变
  console.log(a)  // 123
  function a(){}  // 预编译环节进行变量提升,执行时不看此行代码
  console.log(a)  // 123
  var b = function(){}  // 函数声明,对b重新赋值,AO对象改变
  console.log(b)   // function b(){}
  function d(){}  // 预编译环节变量提升,执行时不再看此行代码
}

实例二

function test(a,b){
  console.log(a); // 1
  c = 0;          // AO更新
  var c;          // 预编译,不看
  a = 3;          // AO更新
  b = 2;          // AO更新
  console.log(b); // 2
  function b(){}; // 预编译,不看
  function d(){}; // 预编译,不看
  console.log(b); // 2
} 
test(1); // 1 2 2
/**
AO1{}
AO2{
  a: undefined,
  b: undefined,
  c: undefined,
}
AO3{
  a: 1,
  b: undefined,
  c: undefined,
}
AO4{
  a: 1,
  b: function a(){},
  c: undefined,
  d: function c(){},
}
end;
**/

实例三

// 引入GO(全局对象)
console.log(test);    // function test(test){,,,,,}
function test(test){
  console.log(test);  // function test(){}
  var test = 234;     // AO改变
  console.log(test);  // 234
  function test(){}   // 预编译,不看
}
test(1);
var test = 123;

执行结果:
// function test(test){,,,,,}
// function test(){}
// 234

解析过程:
/**
页面加载完成,生成GO对象 
GO1{
  test: undefined
}
GO2{
  test: function(test){xxxxx}
}
执行test()钱生成AO对象
AO1{
  test: undefined,
}
AO2{
  test: 1
}
AO3{
  test: function test(){}
}
预编译结束,开始执行
AO4{
  test: 234
}
**/

实例四

function demo(){
  console.log(b);  // undefined
  if(a){
    var b = 100;
  }
  console.log(b);  // undefined
  c = 234;         // 全局变量
  console.log(c);  // 234
}
var a;
demo();
a = 10;
console.logs(c);   // 234

// undefined undefined 234 234

/* 
GO1{
  a: undefined
}
GO2{
  a: undefined,
  demo: function demo(){xxxxx},
}
执行demo函数前预编译,由于c未声明就使用,所以是全局变量
GO2{
  a: undefined,
  demo: function demo(){xxxxx},
  c: undefined
}
a是undefined,if里不执行
输出undefined
GO4{
    a : undefined,
    demo : function demo(){}
    c : 234;
}
//输出234
GO5{
    a : 10,
    demo : function demo(){}
    c : 234;
}
//输出234
*/

本文参考https://juejin.im/post/5aa6693df265da23884cb571

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章