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

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