JavaScript

編程語言 来自维基百科,自由的百科全书

JavaScript

JavaScript(通常縮寫為JS)是一門基於原型頭等函數的多範式進階直譯程式語言[9][10],它支援物件導向程式設計、指令式編程函數式程式設計。它提供方法來操控文字、陣列、日期以及正則表達式等。不支援I/O,比如網絡、儲存和圖形等,但這些都可以由它的宿主環境提供支援。它由Ecma通過ECMAScript實作語言的標準化[9]。目前,它被世界上的絕大多數網站所使用,也被世界主流瀏覽器ChromeFirefoxSafariOpera)所支援。

快速預覽 編程範型, 設計者 ...
JavaScript
Thumb
JavaScript原始碼截圖
編程範型事件驅動函數式指令式
設計者創造者布蘭登·艾克ECMAScript規範的其他關鍵貢獻者
釋出時間1995年12月4日,​29年前​(1995-12-04[1]
目前版本
  • ECMAScript 2024(2024年6月;穩定版本)[2]
  • ECMAScript 2025(2024年3月27日;預發佈版本)[3]
編輯維基數據連結
型態系統動態型別鴨子型別
副檔名
  • .js
  • .cjs
  • .mjs[4]
網站www.ecma-international.org/publications-and-standards/standards/ecma-262/ 編輯維基數據連結
主要實作產品
V8JavaScriptCoreSpiderMonkeyChakra
受影響於
AWK[5]CHyperTalk英語HyperTalkJava[6]LuaPerlPythonSchemeSelf
影響語言
ActionScriptAtScript英語AtScriptCoffeeScriptDartJScript .NETLiveScript英語LiveScriptObjective-J英語Objective-JOpa英語Opa_(programming_language)QMLRakuTypeScript
關閉
快速預覽 副檔名, 網路媒體型式 ...
JavaScript
Thumb
副檔名
.js
網路媒體型式
application/javascript
text/javascript (obsolete)[7]
統一類型標識com.netscape.javascript-source[8]
格式類型腳本語言
關閉

JavaScript與Java在名字和語法上都很相似,但這兩門程式語言從設計之初就有很大不同。JavaScript在語言設計上主要受到了Self(一種原型程式設計語言)和Scheme(一門函數式程式設計語言)的影響[10],在語法結構上它和C語言很相似(如if條件陳述式、switch陳述式、while循環和do-while循環等)[11]

對於客戶端來說,JavaScript通常被實作為一門解釋語言,但如今它已經可以被即時編譯(JIT)。隨着HTML5CSS3語言標準的推行,它還可以用於遊戲、桌面和流動應用程式的開發,以及在伺服器端網絡環境執行(如Node.js)。

歷史

肇始於網景

1993年,國家超級電腦應用中心(NCSA)發表了NCSA Mosaic,這是最早流行的圖形介面網頁瀏覽器,它在萬維網的普及上發揮了重要作用[12]。1994年,Mosaic的主要開發人員創立了Netscape公司,並僱用了許多原來的NCSA Mosaic開發者用來開發Netscape Navigator,該公司的目標是取代NCSA Mosaic成為世界第一的網頁瀏覽器。在四個月內,已經佔據了四分之三的瀏覽器市場,並成為1990年代互聯網的主要瀏覽器[13]

在網絡發展的這些年,網頁只能是靜態的,缺乏在瀏覽器中載入網頁後的動態行為能力。公司的創始人馬克·安德森認為HTML需要一種膠水語言,讓網頁設計師和兼職程式設計師可以很容易地使用它來組裝圖片和外掛程式之類的元件,且程式碼可以直接編寫在網頁標記中。1995年,網景招募了布蘭登·艾克,目標是把Scheme語言嵌入到Netscape Navigator瀏覽器中[14]。但更早之前,網景已經跟昇陽合作,計劃在Netscape Navigator中嵌入Java語言,這時網景內部產生激烈的爭論[15]

網景公司管理層很快決定,最佳的方案是由艾克設計一種新的語言,其語法類似於Java,而不像Scheme或其他現存的腳本語言。為了在其他競爭提案中捍衛JavaScript這個想法,公司需要有一個可以運作的原型。艾克在1995年5月僅花了十天時間就把原型設計出來了[16][17]。最初命名為Mocha,1995年9月在Netscape Navigator 2.0的Beta版中改名為LiveScript,同年12月在Netscape Navigator 2.0 Beta 3中部署時又被重新命名為JavaScript[1][18],這是因為當時網景公司與昇陽電腦公司組成的開發聯盟為了讓這門語言搭上Java這個程式語言「熱詞」,所以才將其臨時改名為JavaScript,這成了日後這成為大眾對這門語言有諸多誤解的原因之一[19]。同年昇陽電腦公司在1995年12月1日正式申請註冊JavaScript的商標,於2000年7月28日獲批 [20],但此後昇陽電腦公司和之後收購它的甲骨文公司從未使用該商標製造過產品,給JavaScript社區帶來了不確定性,阻礙了JavaScript社區的自由發展,直到幾十年後,1.5萬多名JavaScript社區成員於2024年11月22日聯名向美國專利商標局申請終止該商標 [21][22]

微軟採納

微軟公司於1995年首次推出Internet Explorer,引發了與Netscape的瀏覽器大戰。微軟對Netscape Navigator直譯器進行了逆向工程,創建了JScript,以與處於市場領導地位的網景產品同台競爭。JScript也是一種JavaScript實作,這兩個JavaScript語言版本在瀏覽器端共存意味着語言標準化的缺失。發展初期,JavaScript的標準並未確定,同期就有網景的JavaScript和微軟的JScript。除此之外,微軟也在網頁技術上加入了不少專屬物件,使不少網頁使用非微軟平台及瀏覽器無法正常顯示[23][24]。這導致在瀏覽器大戰期間網頁設計者通常會把「用Netscape可達到最佳效果」或「用IE可達到最佳效果」的標誌放在首頁[23][25]

標準化

1996年11月,網景正式向ECMA(歐洲電腦製造商協會)提交語言標準。1997年6月,ECMA以JavaScript語言為基礎制定了ECMAScript標準規範ECMA-262。JavaScript成為了ECMAScript最著名的實現之一[26]。除此之外,ActionScriptJScript也都是ECMAScript規範的實作語言。儘管JavaScript作為給非程式人員的腳本語言,而非作為給程式人員的程式語言來推廣和宣傳,但是JavaScript具有非常豐富的特性。

增長和標準化

在21世紀初Internet Explorer佔主導地位期間,客戶端指令碼停滯不前。這在2004年開始改變,當時Netscape的繼任者Mozilla發佈了Firefox瀏覽器。Firefox受到許多人的好評,從Internet Explorer獲得了巨大的市場份額。[27]

2005年,Mozilla加入了ECMA International,並開始研究ECMAScript for XML(E4X)標準。這導致Mozilla與Macromedia(後來被Adobe Systems收購)合作,他們正在用基於ECMAScript 4草案的ActionScript 3語言實作E4X。目標是將ActionScript 3標準化為新的ECMAScript 4。為此,Adobe Systems將Tamarin實作作為開源專案發佈。然而,Tamarin和ActionScript 3與既定的客戶端指令碼太不同,如果沒有微軟的合作,ECMAScript 4從未取得成果。

與此同時,與ECMA工作無關的開源社區正在發生非常重要的發展。2005年,Jesse James Garrett發佈了一份白皮書,其中他創造了Ajax一詞,並描述了一套技術,其中JavaScript是骨幹,用於建立可以在後台載入數據的Web應用程式,避免了重新載入整頁的需要。這引發了JavaScript的復興時期,由開源庫和圍繞它們形成的社區帶頭。建立了許多新庫,包括jQuery、Prototype、Dojo Toolkit和MooTools。

谷歌於2008年首次推出Chrome瀏覽器,其V8 JavaScript引擎比競爭對手更快。[28]關鍵的創新是及時編譯(JIT)[29],因此其他瀏覽器供應商需要為JIT徹底改革他們的引擎[30]

2008年7月,這些不同的政黨聚集在一起,在奧斯陸舉行會議。這導致在2009年初達成了最終協定,將所有相關工作結合起來,推動語言向前發展。結果是2009年12月發佈的ECMAScript 5標準。

走向成熟

關於該語言的雄心勃勃的工作持續了數年,最終隨着 2015 年ECMAScript 6的發佈而正式形成了廣泛的補充和改進。

Ryan Dahl在 2009 年建立的Node.js引發了 Web 瀏覽器之外 JavaScript 使用的顯着增加。Node 結合了V8引擎、事件循環和I/O API,從而提供了獨立的 JavaScript 執行時系統。截至 2018 年,Node 已被數百萬開發人員使用,並且npm擁有世界上所有包管理器中最多的模組。

ECMAScript 草案規範目前在GitHub上公開維護,並通過定期的年度快照生成版本。對語言的潛在修訂通過全面的提案流程進行審查。現在,開發人員不再單獨檢查即將推出的功能的狀態,而不是版本號。

當前的 JavaScript 生態系統擁有許多庫和框架、已建立的編程實踐以及在 Web 瀏覽器之外大量使用 JavaScript。另外,隨着單頁應用程式和其他大量使用 JavaScript 的網站的興起,已經建立了多個轉譯器來幫助開發過程。

概論

一般來說,完整的JavaScript包括以下幾個部分:

  • ECMAScript,描述了該語言的語法和基本對象;
  • 文件物件模型(DOM),描述處理網頁內容的方法和介面;
  • 瀏覽器對象模型(BOM),描述與瀏覽器進行互動的方法和介面。

JavaScript的基本特點如下:

  • 是一種解釋性腳本語言(代碼不進行預編譯);
  • 主要用來向HTML頁面添加互動行為;
  • 可以直接嵌入HTML頁面,但寫成單獨的js檔案有利於結構和行為的分離。

JavaScript常用來完成以下任務:

  • 嵌入動態文字於HTML頁面;
  • 對瀏覽器事件作出響應;
  • 讀寫HTML元素;
  • 在數據被提交到伺服器之前驗證數據;
  • 檢測訪客的瀏覽器資訊;
  • 控制Cookie,包括建立和修改等;

特性

不同於伺服器端腳本語言(如PHPASP),JavaScript主要被作為客戶端腳本語言在用戶的瀏覽器上運行,不需要伺服器的支援。所以在早期程式設計師比較青睞於JavaScript以減少對伺服器的負擔,而與此同時在安全性上出現了問題。隨着伺服器變得強大,現在的程式設計師更喜歡運行於伺服器端的指令碼以保證安全,但JavaScript仍然以其跨平台、容易上手等優勢大行其道。同時,有些特殊功能(如AJAX)必須依賴JavaScript在客戶端提供支援。隨着引擎(如V8)和框架(如Node.js)的發展,以及事件驅動非同步IO等特性,JavaScript也被逐漸用來編寫伺服器端程式。

以下是ECMAScript通常所實作的特性。

指令式與結構化

JavaScript支援許多C語言的結構化編程語法(如if條件陳述式、while循環、switch陳述式和do-while循環等),但作用域是一個例外。JavaScript在過去只支援使用var關鍵字來定義變量的函數作用域,但ECMAScript 2015中加入了let關鍵字來支援塊級作用域[31]。這意味着JavaScript現在既支援函數作用域又支援塊級作用域。JavaScript還支援自動在陳述式末添加分號,允許忽略陳述式末尾的分號。[32]

弱型別

JavaScript是弱型別的,這意味着變量可以被隱式轉換為另一個類型。[33]

  • 二元運算子+會把兩個運算元轉換為字串,除非兩個運算元都為數字類型。[34]這是因為+也表示字串連接操作;
  • 二元運算子-會把兩個運算元轉換為數字類型;[35]
  • 一元運算子,包括+-,都會把運算元轉換為數字。

下列為變量轉換為字串的例子:

  • 字串類型不變;
  • 數字會轉換為其字串表示;
  • 陣列的元素會轉換為字串,然後連接成通過逗號,分隔的長字串;
  • 其它對象會轉換為[object Object],其中Object中該對象的建構函式名。[36]

類型的隱藏轉換是JavaScript受到批評的原因之一,因為隱藏轉換增加了規則的複雜度和發生錯誤的可能性。[37]

更多資訊 左運算元, 運算子 ...
JavaScript中的隱式轉換[38][39]:
左運算元 運算子 右運算元 結果
[](空陣列) + [](空陣列) ""(空字串)
[](空陣列) + {}(空對象) "[object Object]"(字串)
false(布林值) + ""(空字串) "false"(字串)
"123"(字串) + 1(數字) "1231"(字串)
"123"(字串) - 1(數字) 122 (數字)
關閉

動態化

類型

JavaScript是動態型別的語言,其類型與值而不是與變量相關聯。例如變量可以為數字,隨後又可被賦值為字串。JavaScript提供了包括鴨子型別在內的方法來檢測變量類型。

執行時估值

JavaScript提供eval()函數,可以在執行時直接執行JavaScript陳述式。[40]

基於原型的物件導向

在JavaScript中,對象是關聯陣列,通過原型(prototype,見下)進行擴充。每一個字串鍵值提供對象的一個屬性的名稱,可以通過使用點號(obj.x)或使用方括號(obj['x'])這兩種效果相同的方式來訪問。屬性可以在執行時添加、重定義或刪除。一個對象的大多數屬性(包括來自原型繼承鏈的屬性)都可以通過 for...in循環訪問。[41]

原型

JavaScript使用原型,而許多其它物件導向語言使用類用於實作繼承。原型使得在JavaScript中模擬類別為基的物件導向特徵變成可能。[42]

函數作為對象構造器

函數在JavaScript中兼作為對象建構函式。在函數呼叫前加上new會建立一個原型的實例,並繼承來自建構函式的屬性和方法(包括來自Object原型)。[43]ECMAScript 5提供Object.create方法,可以顯式地建立實例而不是自動從Object繼承。[44]建構函式的prototype屬性決定了用於新對象的內部原型。可以通過修改建構函式的原型的方法來為對象添加新的方法,也可以修改JavaScript的內部對象的原型(如ArrayObject)。儘管可以這麼做,但對Object原型進行修改並不是好的做法。因為大多數JavaScript對象都會從Object繼承,且不會希望其原型被修改。[45]

函數作為方法

和大多數物件導向的語言不同,在JavaScript中函數定義和方法定義沒有明顯區別。唯一的區別在於呼叫時:當函數被作為方法呼叫時,函數的this會指向呼叫此函數的對象。[46]

傳統的類別定義與使用格式

ECMAScript 2015中加入了對classextends關鍵字的支援,使得類的定義與繼承更類似於其他的物件導向語言,同時也更易使用。[47][48]

函數式

在JavaScript中,函數是一等的,函數也被認為是對象。因此,函數可以有屬性和方法,例如call()bind等。[49]巢狀函數指定義於其它函數內部的函數,在外部函數被呼叫時,巢狀函數會被建立。另外,巢狀函數是一個閉包,在外部函數的作用域(包括常數,局部變量和參數)都成為內部函數狀態的一部分,甚至在外部函數執行完畢後,內部函數的狀態依然保留[50]。JavaScript同時也支援匿名函數[51]

其它

執行時環境

JavaScript通常依賴於執行時環境(例如瀏覽器)來提供對象和方法,指令碼可以通過這些對象和方法與環境(例如網頁DOM)進行互動。它還依賴於執行時環境來提供包或匯入指令碼(例如HTML<script>元素)的功能。這本身不是語言功能,但在大多數JavaScript實作中很常見。

承諾

JavaScript的「承諾」(Promise)是一種編程模型,它允許表示可能在未來某個時間點完成或失敗的值。承諾被設計為一個解決非同步編程中所遇到的問題的更簡潔和一致的方法。相比於傳統的回呼函數,它為處理非同步操作提供了一個更清晰的方式。

一個承諾有三種狀態: 待定(Pending): 初始狀態,既不是成功也不是失敗。 已履行(Fulfilled): 意味着操作成功完成。 已拒絕(Rejected): 意味着操作失敗。 承諾的主要特點是它們的狀態一旦改變(從待定到已履行或已拒絕),就不能再次改變。這使得承諾成為一個可靠的資訊來源,無論它們是否成功。

在JavaScript中,你可以使用then()方法來附加回呼函數,這些回呼函數會在承諾達到已履行或已拒絕狀態時執行。還有一個catch()方法,專門用於處理被拒絕的承諾。為了使鏈式呼叫更簡潔,then()catch()都會返回一個新的承諾。ES6(ECMAScript 2015)引入了原生的Promise對象,從此承諾成為JavaScript標準的一部分。此後的版本還提供了額外的實用方法,例如Promise.all()Promise.race(),用於處理多個承諾。

非同步

JavaScript一般來說是單線程的。[52]為了並行地處理事件,JavaScript程式輸入或輸出時使用事件回呼函數執行。這意味着JavaScript可以在等待資料庫查詢返回資訊之前處理滑鼠單擊。ECMAScript 2015引入了Promise用於處理非同步事件,其可以使得傳統的基於回呼的非同步代碼更加清晰簡單。[53][54]

變長參數

JavaScript中函數參數的長度是可變的,在函數內部可以通過arguments對象訪問這些參數。[55]

編程

JavaScript是一門腳本語言,其原始碼在客戶端執行前不需經過編譯,而是將文字格式的字元代碼傳送給瀏覽器,由瀏覽器解釋執行。直譯語言的弱點是安全性較差,而且在JavaScript中,如果一條陳述式執行不了,通常它下面的語言也就無法執行。解決辦法是使用例外處理try {} catch () {}

console.log("a");  //這是正確的
console.log("b");  //這是正確的
console.logg("c"); //這是錯誤的,並且到這裡會停下來
console.log("d");  //這是正確的
console.log("e");  //這是正確的

/* 解決辦法 */
try { console.log("a"); } catch (e) {}  //這是正確的
try { console.log("b"); } catch (e) {}  //這是正確的
try { console.logg("c"); } catch (e) {} //這是錯誤的,但是到這裡不會停下來,而是跳過
try { console.log("d"); } catch (e) {}  //這是正確的
try { console.log("e"); } catch (e) {}  //這是正確的

JavaScript被歸類為直譯語言,因為主流的引擎都是每次執行時載入程式碼並解譯。V8是將所有程式碼解譯後再開始執行,其他引擎則是逐行解譯(SpiderMonkey會將解譯過的指令暫存,以提高效能,稱為即時編譯)。但由於V8的核心部份多數用JavaScript撰寫(而SpiderMonkey是用C++),因此在不同的測試上,兩者效能互有優劣。

與其相對應的是編譯語言(如C語言),以編譯語言編寫的程式在執行之前必須經過編譯,將程式碼編譯為機械碼,才可以執行。

範例

以下是一個簡單的JavaScript Hello World

<!DOCTYPE HTML>
<html>
    <head>
    <title>簡單的JavaScript Hello World</title>
        <script>
            document.write("Hello, world!");   // 於瀏覽器視窗內直接顯示
            alert("Hello, world!");            // 開啟對話視窗顯示
            console.log("Hello, world!");      // 於console裡顯示,需要先開啟開發工具控制台
        </script>
    </head>
    <body>
    HTML內容……
    </body>
</html>

或是在瀏覽器網址列中使用javascript:,以互動方式表示:

javascript:alert("Hello world!");

版本

JavaScript最初開發於1996年,被使用於Netscape Navigator網頁瀏覽器。同年微軟在Internet Explorer發佈了一個實作。由於商標問題,這項實作被命名為JScript。1997年,JavaScript已經被網景公司提交給ECMA制定為標準,稱之為ECMAScript,標準編號ECMA-262。使用顯式版本號聲明對語言的參照,作爲一項Mozilla的特性,已在較新版本中被移除(至少為Firefox 59)。Firefox 4是最後一個需要顯式地在參照時聲明明確版本號的版本(1.8.5)。

下列表格的資訊基於多個參考來源[56][57][58][59]

更多資訊 版本, 發佈日期 ...
版本 發佈日期 基於 Netscape
Navigator
Mozilla
Firefox
Internet
Explorer
Opera Safari Google
Chrome
舊版本,不再支援: 1.0 1996年3月 2.0 3.0
舊版本,不再支援: 1.1 1996年8月 3.0
舊版本,不再支援: 1.2 1997年6月 4.0 - 4.05 3
舊版本,不再支援: 1.3 1998年10月 ECMA-262 1st + 2nd edition 4.06 - 4.7x 4.0 5[60]
舊版本,不再支援: 1.4 Netscape
Server
6
舊版本,不再支援: 1.5 2000年11月 ECMA-262 3rd edition 6.0 1.0 5.5(JScript 5.5)
6(JScript 5.6)
7(JScript 5.7)
8(JScript 5.8)
7.0 3.0-5 1.0 - 10.0.666
舊版本,不再支援: 1.6 2005年11月 1.5 + Array extras + Array and string generics + E4X 1.5
舊版本,不再支援: 1.7 2006年10月 1.6 + Pythonic generators[61] + Iterators + Let 2.0 28.0.1500.95
舊版本,不再支援: 1.8 2008年6月 1.7 + Generator expressions + Expression closures 3.0 11.50
舊版本,不再支援: 1.8.1 1.8 + native JSON support + Minor updates 3.5
舊版本,不再支援: 1.8.2 2009年6月22日 1.8.1 + Minor updates 3.6
舊版本,不再支援: 1.8.5 2010年7月27日 1.8.2 + New features for ECMA-262 5th edition compliance 4.0
關閉

參見

參考文獻

外部連結

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.