JavaScript基礎——你真的清楚JavaScript是什麼嗎?

什麼是JavaScript?

爲前端開發,你是否問過本身或者思考過什麼是JavaScript嗎?JavaScript有什麼特色?若是讓你讓一句話高度介紹,你會怎麼說?小編認爲,在你想深刻一門語言,必需要清楚理解這們語言有什麼特色和其中的運行機制,這是學好一門語言的基礎。前端

JavaScript是一個單線程、非阻塞、異步、解釋性語言。數據庫

單線程是個什麼鬼?

有計算機基礎知識的同窗能夠忽略這部份內容,首先咱們來一塊兒瞭解下計算機基礎知識:線程和進程瀏覽器

打個比方,咱們去超市購物,結帳的時候會有多個收銀窗口,這樣的好處就是在同一時間完成更多交易處理。這就是計算機常說的多併發概念,操做系統是多併發執行任務,由於它同時運行多個進程。進程是執行環境或正在運行的應用程序的實例。例如,你可能一邊瀏覽着網頁、一邊打開編輯器寫着代碼、一邊開着微信聊着天,這都要歸功於計算機能同時運行多個應用進程。微信

應用程序也是能夠處理多併發的,主要是靠線程實現的。在其餘高級語言,若是你熟悉JAVA就會很容易理解,JAVA能夠輕鬆建立多個線程處理併發問題,好比同時處理髮出HTTP請求,查詢數據庫或打開文件。可是JavaScript是單線程的運行環境,它有且只有一個調用棧,它每次只能作一件事,程序每次只能運行一段代碼,這就是單線程。單線程更通俗的解釋就是——全部任務須要排隊,前一個任務結束,纔會執行後一個任務。若是前一個任務耗時很長,後一個任務就不得不一直等着。數據結構

什麼是調用棧?(call stack)——代碼在運行過程當中,會有一個叫作調用棧(call stack)的概念。調用棧是一種棧結構,它用來存儲計算機程序執行時候其活躍子程序的信息。(好比什麼函數正在執行,什麼函數正在被這個函數調用等等信息)。調用棧是解析器的一種機制。多線程

首先一塊兒看下一段簡單的代碼,咱們先了解下Javascript是如何運行的?併發

首先按照函數調用的順序進棧,而後函數執行完了,將值傳給下個函數,出棧,最後將結果輸出。異步

阻塞是個什麼東東?

什麼是阻塞,沒有嚴格的定義什麼是阻塞。僅僅是指代碼運行得很慢,好比說console.log不慢,遍歷從1到10億次很慢,你能夠能夠暫且想一想下,若是你用瀏覽器打開一個網頁,一個網頁確定會涉及到各類數據的請求,圖片、接口數據、CSS文件之類,若是JavaScript不想辦法解決優化單線程加載數據問題的話,咱們瀏覽網頁的體驗多是這樣的:先出來一個空白頁面,過了一會一張圖片出來了,而後在出來一段文字,過了一會接口數據讀取完了,顯示了一段文字,就這樣網頁像擠牙膏似的一點點的顯示出來,這樣的瀏覽體驗你還會看網頁嗎?。所以更白話點在棧裏表現很慢的東西都叫阻塞。async

就像下圖的代碼,小編寫了一個本身調用本身的函數,讓函數進入無線循環的過程,形成了調用棧裏須要執行大量的函數,模擬了一個阻塞,瀏覽器實在沒法承受調用之痛,報錯了!編輯器

祕密武器——非阻塞、異步回調

因爲JavaScript要解決這個問題,必需要突破單線程的瓶頸,「異步回調」就成爲JavaScript的祕密武器,完美的解決了此問題。異步回調讓其擁有了「多線程」的能力,其實並不其然,異步回調是怎麼解決併發問題,阻塞問題,不知道各位思考過背後的運行進制嗎?

維基百科是這麼解釋回調函數的:回調函數就是一個經過函數指針調用的函數。若是你把函數的指針(地址)做爲參數傳遞給另外一個函數,當這個指針被用爲調用它所指向的函數時,咱們就說這是回調函數。回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用於對該事件或條件進行響應。

通俗點回調是一個函數被做爲一個參數傳遞到另外一個函數裏,在那個函數執行完後再執行。有點很差理解,小編在說的直白些就是——B函數被做爲參數傳遞到A函數裏,在A函數執行完後再執行B。

瞭解完異步回調的概念後,咱們來看看JavaScript是如何運行的?首先看看下面一張圖

在介紹這張圖時,咱們先了解下什麼是任務隊列——全部任務能夠分紅兩種,一種是同步任務(synchronous),另外一種是異步任務(asynchronous)。同步任務指的是,在主線程上排隊執行的任務,只有前一個任務執行完畢,才能執行後一個任務;異步任務指的是,不進入主線程、而進入」任務隊列」(task queue)的任務,只有」任務隊列」通知主線程,某個異步任務能夠執行了,該任務纔會進入主線程執行。

主線程從」任務隊列」中讀取事件,這個過程是循環不斷的,因此整個的這種運行機制又稱爲Event Loop(事件循環)。上圖中,主線程運行的時候,產生堆(heap)和棧(stack),棧中的代碼調用各類外部API,它們在」任務隊列」中加入各類事件(click,load,done)。只要棧中的代碼執行完畢,主線程就會去讀取」任務隊列」,依次執行那些事件所對應的回調函數。

「任務隊列」是一個先進先出的數據結構,排在前面的事件,優先被主線程讀取。主線程的讀取過程基本上是自動的,只要執行棧一清空,」任務隊列」上第一位的事件就自動進入主線程。可是,因爲存在後文提到的」定時器」功能,主線程首先要檢查一下執行時間,某些事件只有到了規定的時間,才能返回主線程。

經過下圖將異步函數的執行步驟可視化,讓咱們更加容易理解上訴文字內容。

今天的介紹就到這裏,想必你們都十分清楚JavaScript的特色了,咱們一塊兒瞭解什麼是單線程、進程、阻塞、調用堆棧、異步回調、任務隊列、事件循環等概念,同時又清楚了JavaScript的運行機制,今天的內容你們都學會了嗎。接下來小編將會給你們介紹JavaScript回調,承諾和異步函數,沒理解的同窗建議在反覆看下,沒關注公衆號的,麻煩你們關注微信公衆號「前端達人」

相關文章
相關標籤/搜索