搞懂JS變量提高

本文講解Javascript變量提高引發的問題以及如何規避。javascript

問題

今天看到一道有意思的面試題,考察的還真是JS的基本功,題目以下:java

var name = "world";

(function(){
  if(typeof name === "undefined") {
    var name = "Jack";
      console.log("Hello " + name);
  } else {
    console.log("Hello " + name);
  }
}());

根據if條件能夠得出可能的答案:面試

  • Hello world
  • Hello Jack

正確答案

答案是Hello Jack,可是答案怎麼來的,回答很差可能仍是隻能打50分,有如下兩種理解:瀏覽器

理解1:函數

當即執行函數有獨立的做用域,訪問不到外部name,因此if判斷成立,輸出 Hello Jack

這個理解是不正確的。雖然函數隔離了做用域,可是因爲做用域鏈的關係,JS會從當前做用域一直往上級查找,直到頂級做用域(瀏覽器環境爲window)。code

以下代碼輸出Hello worldip

var name = "world";

(function(){
  console.log("Hello " + name);
}());

理解2:內存

var存在變量提高,因此if在判斷的時候name確實爲undefined,走了if分支,輸出 Hello Jack

變量提高

MDN對變量提高的解釋:作用域

「變量提高」意味着變量和函數的聲明會在物理層面移動到代碼的最前面,但這麼說並不許確。實際上變量和函數聲明在代碼裏的位置是不會動的,而是在編譯階段被放入內存中。get

  • 敲黑板: JavaScript 僅提高聲明,而不提高初始化
  • 函數和變量相比,會被優先提高

根據變量提高理論咱們能夠「模擬」JS實際執行代碼的過程:

var name = "world";

(function(){
  var name; // 變量提高,僅提高聲明,不提高初始化
  if(typeof name === "undefined") {
    name = "Jack";
    console.log("Hello " + name);
  } else {
    console.log("Hello " + name);
  }
}());

函數內部做用域頂級的name初始化時爲undefined,因此會走if分支,輸出Hello Jack。這纔是100分答案!

規避變量提高問題

  1. 在做用域的頂部定義變量
  2. 使用ES6新語法let或const定義變量

技術參考

相關文章
相關標籤/搜索