先從一個簡單的例子出發(先不涉及異步),看看本身是否大體瞭解瀏覽器的執行機制:html
console.log(a); var a=1; function foo(a){ console.log(a); var a=2; console.log(a); } foo(a);
undefined 1 2git
若是你的預測結果不同,那你能夠看看下面幾個常見的誤區:github
答:變量提高只提高變量的聲明,並不進行賦值。其中變量提高發生在預編譯階段,此時a=undefined,預編譯結束後代碼以下
//函數聲明和變量聲明進行提高,且函數聲明優先級更高 function foo(a){ console.log(a); var a=2; console.log(a); } var a; console.log(a); a=1; foo(a);
很明顯第一個結果爲undefined。web
變量聲明在順序上跟在函數聲明和形式參數聲明以後,同時,若是變量名稱跟已經聲明的形式參數或函數相同,則變量聲明不會干擾已經存在的這類屬性。例子中的var a=2,能夠拆分爲var a;a=2;其中a=2是對參數a進行賦值。
首先你須要理解以下幾個概念:數組
JavaScript 中的變量分爲基本類型和引用類型。其中,基本類型存在於棧中,引用類型存在於堆中。在js的執行階段,當執行到a=2這樣的賦值語句時,js引擎線程會先判斷2是基本類型仍是引用類型,若是它是基本類型,則直接對執行棧中的AO進行賦值a=2(AO會在下面的執行上下文中講到),如果引用類型,則在堆中存入2,而後用2在堆中的地址對AO進行賦值。
js的執行環境分爲三種:瀏覽器
js每進入一個執行環境就會建立一個執行上下文,並將它放入執行棧中。執行上下文會在下文講到。安全
js是一門單線程語言,但並不意味着參與js執行過程的線程就只有一個。一個有四個線程參與該過程:
JS引擎線程、事件觸發線程、定時器觸發線程、HTTP異步請求線程。其中,只有JS引擎線程在執行JS腳本程序,其餘三個線程只負責將知足觸發條件的處理函數推動事件隊列,等待JS引擎線程執行。異步
舉一個簡單的例子來講:函數
console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); console.log('script end');
若是還不清楚,能夠看看下圖:性能
首先,這是一個瀏覽器環境,其中主線程操做堆和執行棧,而RunTime中存在着許多web API,當主線程讀取到setTimeOut等API時,它會交給其餘線程來處理(setTimeOut則是定時器觸發線程),定時器觸發線程會先將setTimeOut中的回調函數存放在event table中,當知足觸發條件時(如上面的4ms),就將回調函數推入事件隊列(callback queue)中,等待主線程空閒(執行棧中爲空),回調函數則被推入執行棧中進行執行。
執行上下文可理解爲當前的執行環境,與該運行環境相對應。js引擎每進入一個環境就會建立相應的執行上下文,建立執行上下文的過程當中,主要作了如下三件事件,如圖:
其中,變量對象VO(Variable object)用於存放聲明後的變量、函數和形參。咱們舉一個例子來講:
var a = 10; function test(x) { var b = 20; }; test(30);
對應的變量對象是:
// 全局上下文的變量對象 VO(global) = { a: undefined, test: <reference to function> //<reference to function>是test函數位於堆中的地址 }; // test函數上下文的變量對象 VO(test) = { arguments: { x:undefined, length:1 }, b: undefined };
當預編譯結束,js進入解釋執行階段時,VO就會轉化爲AO(Active object),也就是活動對象。AO中變量和參數的值再也不是undefined,它們的值會隨着js的逐步執行而發生變化。
做用域鏈用於代表上下文的執行順序。上例中的做用域鏈爲:
scopeChain: [VO(test), AO(global)],
this指向當前做用域。這裏不作過多分析。
js的執行分爲三個階段:
一樣,咱們舉一個例子進行分析:
var a = 1; function bar() { var b = 2; function foo() { var c = 3; } foo(); console.log(b) } function coo() { alert("hello") } bar() coo()
咱們解釋一下以上過程:
至此,你已基本理解了js的執行機制。