什麼是 JAVASCRIPT? | 歷史與核心概念總結

前言

做爲程序員,技術的落實與鞏固是必要的,所以想到寫個系列,名爲 why what or how 每篇文章試圖解釋清楚一個問題。javascript

此次的 why what or how 主題:什麼是 JavaScripthtml

釋義

JavaScript - 一種解釋性腳本語言前端

解釋性腳本語言:一類不具有開發操做系統的能力,而是隻用來編寫控制其餘大型應用程序的「腳本」,但其內容的的執行不須要提早編譯的語言。一般做爲別的程序的輸入。java

JavaScript,是一種用於描述網頁邏輯,處理網頁業務的解釋性腳本語言,純文本,其內容做爲瀏覽器的輸入,瀏覽器負責解釋編譯運行其內容。node

目前 JavaScript 也成功被應用於服務端,服務端的 JavaScript 用於描述業務邏輯,其內容做爲 node 的輸入, node 負責解釋編譯運行其內容。webpack

JavaScript 是伴隨着瀏覽器出現的一門特殊的語言,特殊在哪呢? JavaScript 是惟一一門全部瀏覽器都支持的腳本語言,也就說若是你的 WEB 程序想在客戶端作點事,就必定會用到 JavaScript 。別看如今 JavaScript 煊赫一時,但它最開始出現卻僅爲了驗證表單。git

歷史

  • 1990 - 1994,雖然各類瀏覽器開始出現,但瀏覽器僅用做數據展現,並無客戶端邏輯存在。
  • 1994Netscape 公司計劃實現一種瀏覽器腳本語言進行一些簡單的表單驗證。
  • 1995Netscape 公司僱傭了程序員 Brendan Eich 開發這種網頁腳本語言。
  • 1995.5Brendan Eich 用了 10 天,設計完成了這種語言的初版。取名爲:Mocha
  • 1995.9Netscape 公司將該語言更名爲 LiveScript
  • 1995.12NetscapeSun 公司聯合發佈了 JavaScript 語言。
  • 1996.3Navigator 2.0 瀏覽器正式內置了 JavaScript 腳本語言。
  • 1996.8,微軟發佈 Internet Explorer 3.0 ,同時發佈了 JScript ,該語言模仿同年發佈的 JavaScript
  • 1996.11Netscape 公司在瀏覽器對抗中沒落,將 JavaScript 提交給國際標準化組織 ECMA ,但願 JavaScript 可以成爲國際標準,以此抵抗微軟。
  • 1997.7ECMAScript 1.0 發佈。ECMAScript 是一種標準,而 JavaScript 是該標準的一種實現。
  • 1997.10Internet Explorer 4.0 發佈,其中的 JScript 基於 ECMAScript 1.0 實現。
  • 1999IE 5 部署了 XMLHttpRequest 接口,容許 JavaScript 發出 HTTP 請求,爲後來 Ajax 應用創造了條件。
  • 1999.12ECMAScript 3.0 版發佈,獲得了瀏覽器廠商的普遍支持。
  • 2005Ajax 方法(Asynchronous JavaScript and XML)正式誕生,Google Maps 項目大量採用該方法,促成了 Web 2.0 時代的來臨。
  • 2006jQuery 函數庫誕生,做者爲 John ResigjQuery 統一了不一樣瀏覽器操做 DOM 的不一樣實現,被普遍使用,極大下降了 JavaScript 語言的應用成本,推進了語言的流行。
  • 2007.10ECMAScript 4.0 草案發布,對 3.0 版作了大幅升級,但因爲改動幅度過大,遭到了各大瀏覽器廠商的反對。
  • 2008.7,各大廠商對 ECMAScript 4.0 版本的開發分歧太大,ECMA 開會決定,停止 ECMAScript 4.0 的開發,對其中一些已經改善的部分發布爲 ECMAScript 3.1。不久以後就更名爲 ECMAScript 5
  • 2008,由 google 開發的 V8 編譯器誕生。極大提升了 JavaScript 的性能,爲以後 node 的誕生打下了基礎。
  • 2009Node.js 項目誕生,創始人爲 Ryan DahlJavaScript 正式應用於服務端,以其極高的併發進入人們的視野。
  • 2009.12ECMAScript 5.0 正式發佈。同時將標準的設想定名爲 JavaScript.nextJavaScript.next.next 兩類。
  • 2010NPMRequireJS 出現,標準着 JavaScript 進入模塊化。
  • 2011.6ECMAscript 5.1 發佈,而且成爲 ISO 國際標準(ISO/IEC 16262:2011)。
  • 2012,單頁面應用程序框架(single-page app framework)開始崛起,AngularJS 項目出現。
  • 2012,全部主要瀏覽器都支持 ECMAScript 5.1 的所有功能。
  • 2012,微軟發佈 TypeScript 語言。爲 JavaScript 添加了類型系統。
  • 2013ECMA 正式推出 JSON 的國際標準,這意味着 JSON 格式已經變得與 XML 格式同樣重要和正式了。
  • 2013.2Grunt.js 前端構建化工具發佈,前端進入自動化開發階段。
  • 2013.5Facebook 發佈 UI 框架庫 React
  • 2013.8, Gulp.js 3.0 前端構建工具發佈,js 自動化開發變得簡單起來。
  • 2014,尤雨溪發佈 VUE 項目。
  • 2015.3Facebook 公司發佈了 React Native 項目,將 React 框架移植到了手機端,用來開發手機 App
  • 2015.3babel 5.0 發佈,ES6 代碼正式引用於開發,而不須要考慮兼容問題。
  • 2015.6ECMAScript 6 正式發佈,而且改名爲 ECMAScript 2015
  • 2015.6Mozillaasm.js 的基礎上發佈 WebAssembly 項目。
  • 2015.9Webpack 1.0 發佈,模塊系統獲得普遍的使用。
  • 2016.6ECMAScript 2016(ES7) 標準發佈。
  • 2017.6ECMAScript 2017(ES8) 標準發佈,引入了 async 函數,使得異步操做的寫法出現了根本的變化。
  • 2017.11,全部主流瀏覽器所有支持 WebAssembly,這意味着任何語言均可以編譯成 JavaScript,在瀏覽器中運行。
  • 2018.6ECMAScript 2018(ES9) 標準發佈。
  • 2019.6ECMAScript 2019(ES10) 標準發佈。
  • ...

縱觀發展歷史,很容易就能發現其中幾個關鍵點的出現,極大的促進了 JavaScript 的發展。程序員

  1. XMLHttpRequest 接口的出現,JavaScript 開始有了與服務器溝通的能力,誕生了 ajax ,同時也促進了 RestFul API 的發展。
  2. jQuery 函數庫誕生,極大的下降了網頁開發成本。
  3. V8 的出現,下降了 JavaScript 消耗的資源,加快了編譯速度,複雜的 JavaScript 程序開始出現。
  4. Node.js 項目誕生,JavaScript 開始應用在服務端。
  5. NPMRequireJS 出現,JavaScript 正式進入模塊化。
  6. Grunt Gulp Webpack 這些自動化構建工具的出現,極大的下降了開發成本,統一了各類內容的構建方式。
  7. Babel 的出現完全讓前端程序員放開了手腳,毫無顧忌的使用 ES6 而無須擔憂平臺的兼容性問題。
  8. Angular React Vue 的出現了,進一步下降了網頁開發成本,單頁應用開始出現。
  9. ECMAScript 6 標準的公佈以及實現,彌補了 JavaScript 的語言缺陷,JavaScript 更好用了。

直到目前,JavaScript 已經成爲了 GitHub 上最熱門的語言,從前端到後端在到桌面,都有 JavaScript 的身影,但 JavaScript 語言自己的內容並很少,那麼 JavaScript 語言自己都有哪些內容?es6

語法 & 標準庫

JavaScript 的語法,這裏僅羅列一些概念,具體的能夠查看JavaScript開發文檔web

數據類型

JavaScript 中全部的數據都有類型,以下所示:

類型 定義 示例 含義
null 空值 let a = null 一個特殊的空值
undefined 該值未定義 let a 該值聲明瞭但未定義
Number 數值 let a = 1 包括整數、浮點數、科學計數等全部數字
String 字符串 let a = '1' 單個字符也是字符串
Boolean 布爾值 let a = true 僅有 truefalse ,表明真假
Symbol 符號 let a = Symbol(42) 一類永遠都不會相同的值,經常使用做對象的 key
Object 對象 let a = { a: 1 } 一類擁有多個鍵值對的數據

JavaScript 中數據類型除了能夠按照上述的分類方式,還能夠簡單的分爲:基本數據類型(除了 Object 的其餘類型)和引用類型(Object),這和變量的存儲方式有關,這裏不過於深刻,但 JavaScript 數據是如何存儲的?以後會寫,請持續關注~

運算符 & 流程 & 聲明

  • 運算符
  1. 算術 + - * / ** % ++ --
  2. 比較 > >= < <= == != === !==
  3. 布爾運算 ! || && ?:
  4. 二進制運算 | & ~ ^ << >> >>>

在進行算術、比較、布爾運算時,會出現類型轉換,會有一些怪異的表現,那麼 JavaScript 是如何進行類型轉換的?以後會寫,請持續關注~

  • 流程
  1. for(let i = 0; i < n; i++){ ... }
  2. for(let key in obj){ ... }
  3. for(let value of array){ ... }
  4. while(true){ ... }
  5. do{ ... }while(true)
  6. if(true){ ... }else if(true){ ... }else{ ... }
  7. switch(a){ case() ... }

和大多數的語言同樣,都有相似的流程語句。僅須要注意 for...of 循環便可。

  • 聲明
  1. 常量 - const
  2. 變量 - let or var(不建議使用)
  3. 同步函數 - function
  4. 異步函數 - async function
  5. Generator 函數 - function*

ok,JavaScript 的基礎知識就差很少也就這些,這裏僅是羅列,並不過多的深刻,有興趣或是不瞭解的能夠在JavaScript 教程,進行學習。

標準庫

何爲標準庫?

在瞭解 JavaScript 發展史後,咱們都知道,EcmaScriptJavaScript 語言實現的標準,標準除了規定基本的語法外,還定義了一些列 JavaScript 執行環境應該有的對象或是函數,這些與語法無關的其餘內容,就被稱爲標準庫。標準庫主要包含如下內容(一些已廢棄或不推薦使用的就不羅列了):

  • 全局函數
  1. eval()
  2. isFinite()
  3. isNaN()
  4. parseFloat()
  5. parseInt()
  6. decodeURI()
  7. decodeURIComponent()
  8. encodeURI()
  9. encodeURIComponent()
  10. ...
  • 全局對象
  1. Number
  2. String
  3. Boolean
  4. Symbol
  5. Object
  6. Function
  7. Error
  8. Math
  9. Date
  10. RegExp
  11. Array
  12. Map
  13. Set
  14. JSON
  15. Promise
  16. Generator
  17. GeneratorFunction
  18. AsyncFunction
  19. Proxy
  20. Reflect
  21. WebAssembly
  22. ...

具體內容能夠點擊查看,這裏僅是羅列出一些經常使用的函數以及對象,一些對象若是不操做視頻、音頻、圖像等內容也用不到,這裏就不寫了。

宿主環境

JavaScript 做爲一門解釋性腳本語言,其內容只能做爲別的程序的輸入,而這個別的程序,就是宿主環境。那麼宿主環境爲 JavaScript 提供了什麼呢?

  1. 語法支持,宿主環境最重要的就是須要知道 JavaScript 文本內容到底幹了什麼。
  2. 標準庫支持, JavaScript 代碼會使用 EcmaScript 所規定的標準庫,所以必須實現。
  3. 環境實現,不一樣的宿主環境爲了實現不一樣的功能,會提供了不一樣的實現,好比瀏覽器上的 BOMDOMnode 上的 fs path 等模塊。

瀏覽器

做爲 JavaScript 最重要的宿主環境,JavaScript 攜手已經走過了將近 20 年,瀏覽器由於 JavaScript 而大放異彩,JavaScript 也由於瀏覽器露出鋒芒。

瀏覽器爲 JavaScript 提供語法和標準庫支持外,還實現了兩大類 APIDOM(Document Object Model)BOM(Browser Object Model)

DOM

DOM(Document Object Model) - 文檔對象模型。

不一樣於 EcmaScriptDOM 的規範化組織爲 W3C,也就是說 DOM 實際上是 HTML 標準化的一部分,所以 HTML5 最新標準涵蓋一些 DOM API 是正常的。查看 W3C DOM 的最新規範Document Object Model

那麼何爲文檔對象模型?

咱們都知道 HTML 能夠簡單的理解爲標籤的嵌套,嵌套的標籤造成了樹狀結構。DOM 將該樹狀結構提煉成了 JavaScript 中的一個對象 document 經過該對象,JavaScript 就擁有了操做文檔中某個標籤的能力,從而改變標籤的結構,樣式,內容監聽標籤的事件等等。

DOM 涉及的 API 不少,但其 API 都有一個特色,以 標籤 打頭,好比 body.addEventListener document.getElementsByTagName 等等,能夠經過如下內容進行學習:

BOM

BOM(Browser Object Model) - 瀏覽器對象模型。

BOM 其實到目前尚未一個規範化組織來制定標準,所以各個瀏覽器的實現徹底按照本身的標準來,MDN 上也沒有專門的介紹頁面,說實話有點慘,但雖然沒有標準,各個瀏覽器實現的 API 卻基本相同。

BOM 能夠簡單的理解爲瀏覽器實現了一套 API 使得 JavaScript 能與瀏覽器進行交互。相關的 API 所有放在 window 對象下。

window 對象主要包含如下對象:

  • document - 對 DOM 的引用
  • frames - 對當前頁面中的 iframe 的引用
  • history - 瀏覽器瀏覽記錄相關 API
  • location - 瀏覽器地址相關 API
  • localStorage - 本地數據存儲
  • sessionStorage - 會話級別的數據存儲
  • navigator - 瀏覽器導航信息相關 API
  • screen - 屏幕信息

Node

Node 做爲 JavaScript 服務端的宿主環境,除了提供了語法和標準庫的支持外,還實現了一系列的模塊,每一個模塊都有具體的做用,具體能夠查看Node 官方文檔

其實異步的編程模式是不容易被應用在服務端的,或者說服務端更偏向於同步模式。

服務端的極大多數代碼都須要運行在一個同步的環境下,好比數據庫的查找,文件的讀取,請求結果的讀取等等,若是在都將邏輯寫在異步的回調中,代碼將變得的難以解讀,並且代碼編寫也會變得複雜起來。好比須要安裝順序讀取 10 次外部接口的數據,同步模式下,只要按照順序從前日後寫便可,而異步模式只能嵌套加嵌套(或者 Promise.then )不只寫出來的代碼難以讀懂,代碼也難以維護。

可是爲何 Node 仍是大熱呢?我的感受有如下幾個緣由:

  1. 前端自動化打包的出現。
  2. 雖然異步模式不適合服務端,但卻極其符合請求的過程:請求觸發任務。
  3. 主線程僅分發任務,而不須要處理讀取文件,數據庫等耗時邏輯,不會致使程序堵塞,併發量能夠達到很高。
  4. 其數據結構與前端須要的結構一致(原生支持 JSON)。
  5. 語法靈活,直接操做數據,屏蔽或是添加一些字段,處理一些前置邏輯。
  6. 簡單,包括環境搭建簡單,啓動簡單程,序編寫簡單,還有 NPM 上各類庫。
  7. ES8 AsyncFunction 異步函數的出現,將異步模式的寫法向同步寫法趨近。代碼編寫變得簡單起來。
  8. 前端人直接上手?

對於第 8 點,我持中立態度。大前端的概念層出不窮,我想你們須要冷靜冷靜,不妨上手寫個 Node 程序,感覺下前端異步編程是否真正的適合服務端?還有服務端雖然環境統一,但涉及的概念極多,雖然可能在本身寫的小項目中並不會涉及,可是真正使用倒是會用到的,因此對於 Node 能作什麼,個人理解以下:

  1. 做爲前端開發的自動化工具,webpack gulp 等,語法一致,都能看懂,無非增長了一些文件讀取,字符串解析。
  2. 爬蟲,抓取一些本身敢興趣的東西。對於本身的小程序,放開了手作,數據量不大,怎麼整都行。
  3. 數據預處理,在大型項目中,做爲請求中轉站的存在,返回更加適合前端的數據,或是將前端過來的數據更加適合後端程序,也就是數據映射。在日後交給專業的後端大佬們便可,咱們就無論了。

Electron

Electron 做爲一個跨平臺的 GUI 工具,使用 ChromiumNode 構建,實現了使用 JavaScript 開發桌面應用程序,也能夠算是一個 JavaScript 的宿主環境,但其實至關於實現了一個瀏覽器, JavaScript 也被分爲兩部分,這兩部分的宿主環境分別爲 Node 和瀏覽器。具體能夠查看Electron 官網

Event Loop

無論 JavaScript 程序的運行在 Node 端仍是運做在瀏覽器端,都是以單線程的形式運行在宿主環境下,那麼 JavaScript 是如何處理多任務的呢?

異步 + Event Loop

簡單描述下:JavaScript 會調用宿主環境提供的 API 處理不一樣的任務(這些任務運行在別的線程)並設置這些任務的回調,當這些任務完成時,會在事件隊列中放入任務對應的回調,而 JavaScript 主線程會不斷的去處理事件隊列中的任務,這個過程就被稱爲 Event Loop

因爲這個過程並不在 ECMAScript 所規定的規範中,所以不一樣的宿主環境實現是有區別的,具體能夠查看我以前寫的文章:

語言特色

每種語言都有本身的特色,JavaScript 也不例外,下面就談談 JavaScript 使人着迷,或是苦惱的地方。

數據存儲

每種編程語言都須要處理數據和變量的關係,JavaScript 也不例外。但做爲腳本,它須要運行在一個特定的宿主環境,那麼這個宿主環境儲存了 JavaScript 運行時產生的全部數據,又因爲閉包的存在,使得這些數據能改被各類各樣的變量所引用,而 JavaScript 中變量又是無類型的,各類奇奇怪怪的賦值方式,會致使各類奇奇怪怪的結果,這能夠定義爲複雜,但也能夠定義爲靈活。熟悉它你能夠暢遊在 JavaScript 的世界中,笑談程序;而霸王硬上弓,卻會陷入無盡的 bug 中。

那麼 JavaScript 中數據是如何存儲的?請持續關注 ~ 爭取說清楚。

做用域 & 閉包

做用域你們都很熟悉,由雙大括號產生(ES6+),內層變量能夠引用到外層變量,而外層變量卻對內層變量無能爲力。但函數的閉包卻打破了這層限制,可讓外部程序有了改變或獲取內部變量的能力,同時因爲數據存儲的緣由,外部程序在必定狀況下甚至對內部變量能夠隨心所欲。

那麼 到底何爲做用域?閉包在這裏扮演的什麼角色?請持續關注 ~

函數

JavaScript 是一種函數先行的語言,表如今代碼上爲:能夠直接定義 function 或是直接將 function 賦值給某個變量。

函數,何爲函數?函數能夠理解爲一種行爲,一段過程,或是一個任務,而這些都有一個顯著的特色,有起始點和終點。對應到函數上即爲入參和返回值,在面向對象編程被大肆宣傳的狀況下,函數式編程卻在發揮着獨特的魅力,以其天然清晰簡潔的編程方式,吸引着衆人的眼光。

函數式編程式一個極大的內容,什麼是函數式編程光解釋是沒有用的,只有本身親自上手體驗一把才能感覺到它的魅力。

有興趣的朋友能夠翻閱JS 函數式編程指南

原型鏈

前面說到,JavaScript 是一種函數先行的語言,那麼 JavaScript 就不能面向對象了?錯!ES6 class 語法的出現,標誌着 JavaScript 徹底是可以面向對象的。查看通過 babel 轉碼後的 ES5 兼容代碼,能夠清楚的知道 class 僅僅只是一個語法糖,否則如何進行轉碼呢?而面向對象實現的關鍵是 JavaScript 的另一個特色:原型鏈(prototype)。

那麼 何爲原型鏈(prototype)?原型又是什麼?請持續關注 ~ 爭取說清楚。

this

談到 this 相信大部分面向對象編程語言的 coder 都很熟悉,經常出如今對象所屬的方法中,JavaScript 表現出來的行爲和這些語言一致,但其本質倒是極大的不一樣,由於在每個函數下都有 this 的存在,那麼 this 究竟是什麼?其所表明的又是什麼內容?這和 JavaScript 的數據存儲有點關係,所以在不弄懂數據存儲前,this 每每難以預測。

this 究竟是如何取值的,在 JavaScript 中數據是如何存儲的?中會有提到,請持續關注 ~

箭頭函數

已經說了函數,爲什麼還要單獨寫個箭頭函數?相信你們對於箭頭函數的理解僅僅在簡化的正常函數上,但箭頭函數和用 function 聲明的函數是有區別的,試想一想,在 VUE 文檔中是否有這麼一句話:XXX 只接受 function。這個 function 不表明箭頭函數。那麼箭頭函數究竟是什麼?和普通函數又有什麼區別?什麼狀況下該使用箭頭函數呢?

請看以後的文章:什麼是箭頭函數?

其餘

JavaScript 語言的特色還有不少,ES6 ~ ES10 陸陸續續更新很多內容,包括 Promise Proxy Iterator Generator async 等不少內容,這些都是語言上的更新,具體的使用查看文檔便可。

ECMAScript 6 入門

固然也推薦推薦以前在看《ECMAScript 6 入門》時,寫下的筆記ecmascript6。歡迎查閱~~

模塊化

JavaScript 的模塊化由 RequireJs(AMD)開啓,終結於 ES6(Module)規範,中間經歷了 SeaJS(CMD)Node(CommonJS)。目前經常使用的爲 CommonJS(Node)Module(ES6 + Babel),其餘的咱們能夠略過。

CommonJS

CommonJSNode 端的模塊系統,內置 3 個變量 require exportsmodule。經過 require 引入模塊,exports 對外導出,module 保存該模塊的信息。以下所示

'use strict';

var x = 5;
function addx (value){
    console.log( x + value );
}

exports.addx = addx;
複製代碼

相信你們都知道,導出還有一種寫法

module.exports.addx = addx;
// or
module.exports = { addx };
複製代碼

其實只要知道 module.exports === exports // true,那麼一切就解釋的通了,exports 僅爲 module.exports 的一個引用,可是如下寫法是有問題的

exports = { addx };
複製代碼

出現問題的緣由是 exports 只是一個引用,若是從新賦值的話會致使該變量引用到另外一個數據上,這樣的結果就是 module.exports === exports // false,而模塊的信息是以 module 爲標準的,所以就變成了無導出。那若是究其緣由到底爲何會發生引用變化,能夠查看 JavaScript 中數據是如何存儲的?雖然還沒寫,但確定會寫的。

Module

ModuleES6 推出的模塊化規範,目的在於統一各類不一樣的規範,由 import 導入 export 導出。以下所示

import { stat, exists, readFile } from 'fs';

export const a = '100'; 
// or
const a = '100';
export {
    a
}
複製代碼

常見的導入語句有

  1. import { xxx } from 'a'; - 從 a 中導出 xxx 的屬性或方法,數據由 aexport 導出
  2. import { xxx as yyy } from 'a'; - 從 a 中導出 xxx 的屬性或方法並重命名爲 yyy,數據由 aexport 導出
  3. import xxx from 'a'; - 從 a 中導出默認值,並賦值爲 xxx,數據由 aexport default 導出

常見的導出語句有

  1. export const a = 1; - 導出一個常量,名字爲 a 值爲 1
  2. export { a }; - 導出名字爲 a 的屬性或方法,其值爲做用域中變量 a 的值
  3. export { a : b }; - 導出名字爲 a 的屬性或方法,其值爲做用域中變量 b 的值,其上爲 export { a : a } 的縮寫
  4. export default a; - 導出默認值,其值爲做用域中變量 a 的值
  5. export default 1; - 導出默認值,其值爲 1

常見的錯誤導出語句

  1. export a;
  2. export default const a = 1;

以上是常見的錯誤導出語句,如何避免?只要記住如下規則便可:

  1. export 導出的值,必需要有名字,constlet 這些聲明語句規定了該值的名字,{a: b},也規定了名字。
  2. export default 僅導出值,所以不須要有特殊的方式規定名字。

總結

慣例,問幾個問題

  1. 什麼是解釋性腳本語言?
  2. EMCAScriptJavaScript 是什麼關係?
  3. JavaScript 都有哪些數據類型?
  4. JavaScript 的流程控制語句與運算符都有哪些?
  5. JavaScript 的語言特色是什麼?
  6. JavaScript 模塊是如何定義的?

參考

最後的最後

該系列全部問題由 minimo 提出,愛你喲~~~

相關文章
相關標籤/搜索