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

你們好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新......前端

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

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

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

// 代碼段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() 函數。segmentfault

爲何會這樣呢?這就涉及到js中的變量提高和函數提高的具體過程了。微信

一、變量的提高

js是怎麼建立變量的呢?函數

以下面的代碼:學習

var a = 1;
var b = 2;

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

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

因此 js 並非在咱們定義一個變量的時候,聲明完成以後當即賦值,而是把全部用到的變量所有聲明以後,再到變量的定義的地方進行賦值,變量的聲明的過程就是變量的提高。3d

因此咱們看下下面的栗子:code

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運行到這裏的時候,纔會進行賦值操做,而沒有運行到的變量,不會進行賦值操做。

因此變量的提高,提高的實際上是變量的聲明,而不是變量的賦值。

二、函數的提高

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

三、變量提高和函數提高的順序

在做用域中,無論是變量仍是函數,都會提高到做用域最開始的位置,不一樣的是,函數的提高後的位置是在變量提高後的位置以後的。

舉個栗子:

下面的代碼輸出什麼?

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();

四、參考連接

js變量提高與函數提高的機制: http://www.javashuo.com/article/p-nudwgxqp-eg.html

相關文章
相關標籤/搜索