js變量提升與函數提升的詳細過程


大家好,這里是「 從零開始學 Web 系列教程 」,並在下列地址同步更新......

在這里我會從 Web 前端零基礎開始,一步步學習 Web 相關的知識點,期間也會分享一些好玩的項目。現在就讓我們一起進入 Web 前端學習的冒險之旅吧!

js變量提升與函數提升的詳細過程

先來看兩個栗子,下面的兩段代碼分別輸出什么?

// 代碼段1
function foo() {
  var a = 1;
  function a() {}
  console.log(a);
}
foo();

// 代碼段2
function foo() {
  var a;
  function a() {}
  console.log(a);
}
foo();

答案是:代碼段1打印的是1,代碼段2打印的是 a() 函數。

為什么會這樣呢?這就涉及到js中的變量提升和函數提升的具體過程了。

1、變量的提升

js是怎么創建變量的呢?

如下面的代碼:

var a = 1;
var b = 2;

js在解析上面的代碼的時候,其實會按照下面的方式進行解析的:

var a;
var b;
a = 1;
b = 2;

所以 js 並不是在我們定義一個變量的時候,聲明完成之后立即賦值,而是把所有用到的變量全部聲明之后,再到變量的定義的地方進行賦值,變量的聲明的過程就是變量的提升。

所以我們看下下面的栗子:

function foo() {
  var a = 1;
  console.log(a);
  console.log(b);
  var b = 2;
}
foo();

上面的代碼在js的眼中是這樣解析的:

function foo() {
  var a;
  var b;
  a = 1;
  console.log(a); // 1
  console.log(b); // undefined
  b = 2;
}
foo();

所以輸出的 a 的值為1, b的值為 undefined。

變量在聲明提升的時候,是全部提升到作用域的最前面,一個接着一個的。但是在變量賦值的時候就不是一個接着一個賦值了,而是賦值的位置在變量原本定義的位置。原本js定義變量的地方,在js運行到這里的時候,才會進行賦值操作,而沒有運行到的變量,不會進行賦值操作。

所以變量的提升,提升的其實是變量的聲明,而不是變量的賦值。

2、函數的提升

函數的提升和變量的提升類似,都是提升到作用域的最開始的位置,只不過變量的提升是分兩步的,第一步是變量聲明的提升,第二步是變量的賦值。而函數的提升是直接將整個函數整體提升到作用域的最開始位置,相當於剪切過去的樣子。

3、變量提升和函數提升的順序

在作用域中,不管是變量還是函數,都會提升到作用域最開始的位置,不同的是,函數的提升后的位置是在變量提升后的位置之后的。

舉個栗子:

下面的代碼輸出什么?

function foo() {
  console.log(a);
  var a = 1;
  console.log(a);
  function a() {}
  console.log(a);
}
foo();

上面的代碼在js眼中是這樣解析的:

function foo() {
  var a;
  function a() {}
  console.log(a); // a()
  a = 1;
  console.log(a); // 1
  console.log(a); // 1
}
foo();

所以從上面的栗子可以看到,變量的提升是在函數提升之前的,但是變量賦值的部分是在js原型到變量定義的位置才給變量賦值的,而函數提升是相當於直接剪切到最前面的。

我們再看一個更加復雜一點的栗子:

function foo() {
  console.log(a);
  var a = 1;
  console.log(a);
  function a() {}
  console.log(a);
  console.log(b);
  var b = 2;
  console.log(b);
  function b() {}
  console.log(b);
}

foo();

js是這樣解析的:

function foo() {
  var a;
  var b;
  function a() {}
  function b() {}
  console.log(a); // a()
  a = 1;
  console.log(a); // 1
  console.log(a); // 1
  console.log(b); // b()
  b = 2;
  console.log(b); // 2
  console.log(b);// 2
}
foo();

最后,注意:只有聲明的變量和函數才會進行提升,隱式全局變量不會提升。

下面的栗子中,b不會進行變量提升。

function foo() {
  console.log(a);
  console.log(b); // 報錯
  b = 'aaa';
  var a = 'bbb';
  console.log(a);
  console.log(b);
}
foo();

4、參考鏈接

js變量提升與函數提升的機制: https://segmentfault.com/a/1190000008568071


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM