首頁 web前端 js教程 詳解JavaScript是如何運作的

詳解JavaScript是如何運作的

Nov 26, 2019 pm 03:24 PM
javascript node.js typescript

詳解JavaScript是如何運作的

什麼是JavaScript?

讓我們來確認JavaScript的定義:JavaScript 是一門解釋型的動態語言。

解釋型語言是相對於編譯型語言存在的,原始碼不是直接編譯為目標程式碼,而是轉成中間程式碼,再由解譯器對中間程式碼進行解釋運行。

主流程式語言有編譯型(如 C )、解釋型(如 JavaScript)、和半解釋半編譯(如 Java)這幾大類型。

【相關課程推薦:JavaScript影片教學

#程式碼是怎麼運作的?

首先我們來了解程式碼是怎麼運作的。

我們知道,程式碼是由CPU執行的,而目前的CPU並不能直接執行諸如if…else之類的語句,它只能執行二進位指令。但是二進位指令對人類實在是太不友善了:我們很難快速準確的判斷一個二進位指令1000010010101001代表什麼?所以科學家發明彙編語言。

組合語言

組合語言其實就是二進位指令的助記符。

假設10101010代表讀取記憶體操作,記憶體位址是10101111,暫存器位址是11111010,那麼完整的操作101010101010111111110110 就代表讀取某個記憶體位址的值並載入到暫存器,而組譯語言並沒有改變這個操作方式,它只是二進位指令的對應:

LD:10101010 
id:10101111
R:11111010
登入後複製

這樣上述指令就可以表達為LD id R ,大大增強了程式碼的可讀性。

但是這樣還不夠友好,CPU只能執行三地址表達式,和人的思考方式、語言模式相距甚遠。所以偉大的科學家又發明了高階語言。

高級語言

“程式碼是寫給人看的,不是寫給機器看的,只是順便電腦可以執行而已。”

高階語言之所以稱之為“高級”,就是因為它更符合我們的思維和閱讀習慣。 if…else這種語句看起來要比1010101010舒服的多了。但是電腦並不能直接執行高階語言,所以還需要把高階語言轉換成組合語言/機器指令才能執行。這個過程就是編譯。

JavaScript 需要編譯嗎?

JavaScript毫無疑問是高階語言,所以它肯定需要編譯後才能執行。但為什麼我們又稱之為解釋型語言呢?它和編譯型語言、半解釋半編譯型語言又有什麼差別呢?我們先從編譯說起。

編譯

之前我們已經了解編譯的概念,下面我們來聊聊平台:同樣一份C 程式碼在Windows上會編譯成.obj文件,而在Linux上則產生.o文件,兩者不能通用。這是因為一個可執行檔除了程式碼外還需要作業系統 API、記憶體、執行緒、進程等系統資源,而不同的作業系統其實作也不盡相同。例如我們熟悉的I/O多路復用(事件驅動的靈魂),在Windows上的實作方案就是IOCP方案,在Linux上是epoll。所以針對不同的平台,編譯型語言需要分別編譯,甚至需要分別寫,而且產生的可執行檔其格式並不相同。

跨平台

Java在此之上更進一步,它透過引入字節碼實現了跨平台運行:無論是在什麼作業系統上.java檔案編譯出的都是.class檔案(這就是字節碼文件,一種中間形態的目標碼)。然後Java對不同的系統提供不同的Java虛擬機器用來解釋執行字節碼檔案。解釋執行並不產生目標程式碼,但其最終還是要轉為彙編/二進位指令來給電腦執行的。

假如我們自己完全獨立的新寫一個簡單的作業系統,那它能不能運行Java呢?很顯然是不能的,因為並沒有這個系統對應的JVM。所以Java的跨平台、任何其他語言的跨平台,都是有限制的。

Java採用半解釋半編譯的好處就是大幅提升了開發效率,然而相應的則降低了程式碼的執行效率,畢竟虛擬機器是有效能損失的。

解釋執行

JavaScript則更進一步。它是完全的解釋執行,或稱為即時編譯。它不會有中間程式碼生成,也不會有目標程式碼生成。這個過程通常由宿主環境(如瀏覽器、Node.js)包辦。

編譯過程

#

现在我们确认了,即使是解释执行的语言,也是需要编译的。那么代码是如何编译的呢?我们来简单了解一下。

词法分析

词法分析会把语句分解成词法单元,即Token。

function square(n){
 return n*n;
}
登入後複製

这个函数会被词法分析器识别为function square(n){return,,n ,*n}并且给它们加上标注,代表这是一个变量还是一个操作。

语法分析

这个过程会把Token转化成抽象语法树(AST):

{
 type:'function',
    id:{
        type:'id'
        name:'square'
    },
    params:[
        {
            type:'id',
            name:'n'
        }
    ]
    ...
}
登入後複製

优化及代码生成

在这一步编译器会做一些优化工作,比如删除多余运算、删除未用赋值、合并部分变量等等操作,最后生成目标代码。

由于即时编译型语言的编译通常发生在运行前几微秒,所以编译器来不及做太多的优化工作。这也是相比编译型语言,早期JavaScript性能孱弱的原因之一。不过就现在而言,益于 V8 引擎(相比早期的JavaScript的引擎转换成字节码或解释执行,Node.js可以用 V8 提供的 JS2C 工具将 JavaScript 转译为 C++代码),JavaScript 和其他语言性能上的差距已经不足为道了。

链接及装载

目标代码基本不能独立运行。应用程序一般都会由多个部分(模块)组成 ,比如C++中一个简单的输出就要引入标准库 iostream

#include <iostream>
using namespace std;
int main(){    
    cout <p>编译器需要把多份目标代码(库)链接起来才能生成可执行文件。至此,我们简单的了解了编译过程。但实际上编译比我们所讲的要复杂得多,在此就不在展开了。</p>
<p><strong><span style="font-size: 18px;">什么是动态语言,动态类型?</span></strong></p>
<p>我们还知道,JavaScript是动态语言。那么什么是动态语言?</p>
<p>通常来说,这是指在运行时代码可以根据某些条件改变自身结构的语言。比如JavaScript在运行时新的函数、对象、甚至代码都可以被引进(eval);又比如Objective-C,它也可以在运行时修改对象,但它不能动态创建类,也没有 eval 方法。那Objective-C算是动态语言吗?所以我认为,动态语言是个程度的问题,我们不必在这个概念上太过纠结,可以更多的关注其应用。APP中常用的热更新功能就是基于动态语言特性而得以实现的。</p>
<p>JavaScript又是一门动态类型的语言,动态类型又是什么?动态类型的定义倒是很明确:数据类型不是在编译阶段确定,而是在运行时确定。</p>
<p>那么 TypeScript 是什么类型的语言呢?它有静态类型检查,它是静态语言吗?实际上它只是 JavaScript 的一个方言。TypeScript 最终还是要转译为 JavaScript 才能执行(tsc),就如同我们使用babel 把 ES6 代码转译为 ES5 一样。这个过程严格上来说不是编译。</p>
<p>TypeScript 最大的优势就是静态类型检查和类型推断,这是 JavaScript 严重缺失的能力。但实际上如果我们忽略IDE 给的报错提示强行运行 TS 代码,也还是有几率能够成功跑起来的。</p>
<p><span style="font-size: 18px;"><strong>错误</strong></span></p>
<p>刚刚我们提到报错,不妨再扩展说一说错误。通常来说错误分为以下几种:</p>
<ul>
<li>编译时错误</li>
<li>链接时错误</li>
<li>运行时错误</li>
</ul>
<p>是不是和编译过程能够严格对应起来?</p>
<p><strong>编译时错误</strong></p>
<p>编译时错误分为:</p>
<ul>
<li>
<p>语法错误</p>
<pre class="brush:php;toolbar:false">var str ='s ;
登入後複製

这就是典型的语法错误,这种代码无法生成AST,在词法分析阶段就会报错。通常我们这么写代码,IDE 就会报错。这是IDE的优化工作,和词法分析相关。

  • 类型错误

    编译器会检查我们声明的变量和函数的类型,JavaScript中我们非常熟悉的Type Error:undefined is not object就是此类错误。

  • 链接时错误

    在链接阶段发生的异常。这种情况 JavaScript 中比较少见,在编译型语言中比较常见。

    运行时错误

    这是最难排查的错误了,举例来说:

    int pider(int a,int b){
        return a/b;
    }
    登入後複製

    上面的代码在编辑编译、链接阶段都没问题,也能够正常的生成可执行文件。但是一旦如此使用pider(1,0)就会报错了,这就是典型的运行时错误。通常来说运行时错误都是程序不够健壮导致的。

    JavaScript中最常见的十个错误:

    下图是某错误处理平台收集统计的JavaScript Top10 错误,其中7个TypeError,1个 ReferenceError:

    詳解JavaScript是如何運作的

    顯然這 8 種問題,我們都能用 TypeScript 在編碼早期及時應對。

    結論

    現在我們已經了解JavaScript是如何運作的。但了解這些能夠幫我們寫出更好的程式碼嗎?

    答案是肯定的。且不說TypeScript能夠幫助我們完善類型檢查和類型推斷,JavaScript的作用域、this也是和編譯過程強相關的;而目前主流的小程式框架都能夠支援一套程式碼、多個平台,相信讀完本文後,你大致也了解了這些技術背後的原理。
    Happy Hacking!

    本文來自 js教學 欄目,歡迎學習!

    以上是詳解JavaScript是如何運作的的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

    熱AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智慧驅動的應用程序,用於創建逼真的裸體照片

    AI Clothes Remover

    AI Clothes Remover

    用於從照片中去除衣服的線上人工智慧工具。

    Undress AI Tool

    Undress AI Tool

    免費脫衣圖片

    Clothoff.io

    Clothoff.io

    AI脫衣器

    AI Hentai Generator

    AI Hentai Generator

    免費產生 AI 無盡。

    熱門文章

    R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
    2 週前 By 尊渡假赌尊渡假赌尊渡假赌
    倉庫:如何復興隊友
    4 週前 By 尊渡假赌尊渡假赌尊渡假赌
    Hello Kitty Island冒險:如何獲得巨型種子
    3 週前 By 尊渡假赌尊渡假赌尊渡假赌

    熱工具

    記事本++7.3.1

    記事本++7.3.1

    好用且免費的程式碼編輯器

    SublimeText3漢化版

    SublimeText3漢化版

    中文版,非常好用

    禪工作室 13.0.1

    禪工作室 13.0.1

    強大的PHP整合開發環境

    Dreamweaver CS6

    Dreamweaver CS6

    視覺化網頁開發工具

    SublimeText3 Mac版

    SublimeText3 Mac版

    神級程式碼編輯軟體(SublimeText3)

    如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

    如何使用WebSocket和JavaScript實現線上語音辨識系統

    WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

    WebSocket與JavaScript:實現即時監控系統的關鍵技術

    如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

    如何使用WebSocket和JavaScript實現線上預約系統

    如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

    如何利用JavaScript和WebSocket實現即時線上點餐系統

    簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

    簡易JavaScript教學:取得HTTP狀態碼的方法

    JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

    JavaScript與WebSocket:打造高效率的即時天氣預報系統

    如何在JavaScript中取得HTTP狀態碼的簡單方法 如何在JavaScript中取得HTTP狀態碼的簡單方法 Jan 05, 2024 pm 01:37 PM

    如何在JavaScript中取得HTTP狀態碼的簡單方法

    javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

    javascript如何使用insertBefore

    See all articles