本人在大學時很是癡迷java,認爲java就是世界上最好的語言,偶爾在項目中會用到一些javascript,但基本沒放在眼裏。較全面的接觸javascript是在實習的時候,經過此次的瞭解發現,javascript實際上是一門很是優秀並且有意思的語言,從那時開始喜歡上了這門語言。javascript
javascript裏面不少的概念和目前主流的語言是很是不同的,它更多的是繼承了函數式編程語言的特色。雖然語言的初版的設計聽說只花了七天時間,但其血統仍是挺好的。我的認爲javascript之因此會經久不衰而且應用愈來愈普遍,和其血統是離不開的,它可能恰好觸及到某些「本質」的東西。固然不是要鼓吹「javascript是世界上最好的語言」,javascript語言自己是有許多瑕疵的,這也是被許多人詬病的地方。它優秀的地方設計得很是好用,可以知足絕大多數的使用場景,一些小瑕疵只要稍加註意,並不會產生太大的影響。java
對於有必定編程經驗的人來講,第一次接觸javascript必定會以爲很是簡單,會有似曾相識的感受,但若是輕視它,不去理解它的核心特色,必定會受到懲罰,讓你一臉懵逼。本文就整理了幾個核心的須要理解的知識點,但願可以幫助有編程基礎的初學者快速理解javascript。node
javascript數據類型設計得很是簡單,總共只有6中,分別是boolean、string、number、undefined、object,function。通常將可以經過typeof運算符區分的歸爲一種數據類型。其中object,function爲引用類型,剩下都爲基本類型。javascript的數據類型雖然簡單,但有幾個地方須要特別注意一下。編程
number:
number類型底層採用雙精度浮點數存儲,可以表示整數,也能表示小數。因爲這個緣由,number可以安全表示的整數範圍是-9007199254740991 ~ 9007199254740991,超出則可能丟失精度。還好比0.1 + 0.2,其結果爲:0.30000000000000004。number類型有個特殊值NaN,表示「不是個數字」,好比1/'a'就會返回NaN。後端
undefined:
這是一種很是特殊的數據類型,表示未賦值。變量或屬性定義後未賦值就爲undefined。這種數據類型用處很少,通常只是拿來區分有無賦值。安全
object:
object類型涵蓋的東西很是廣,Array,RegExp這些內置類型的對象也是object類型。null是一個很是特殊的對象,表示空對象,和undefined很像,只不過null是對象類型。閉包
function
函數雖然被當作一種數據類型,但其本質仍是一種特殊的對象,是從Object繼承而來的。併發
我的認爲,函數是javascript裏面設計最巧妙的一個地方,許多有意思的特性都是圍繞函數展開的,好比閉包和繼承等。javascript裏的函數仍是「一等公民」,可以做爲參數傳遞、返回值返回,使用上極其靈活。
理解函數的執行首先要理解做用域的概念。在ES6以前,javascript裏只有全局和函數做用域兩種做用域,到ES6才引入了塊級做用域。異步
函數在執行時會建立一個執行環境,push到執行棧的頂端,執行環境中就包含了當前函數的做用域。做用域包含了當前函數的局部變量以及內置的變量好比this,arguments。函數做用域是在運行時肯定的,非運行時討論做用域是沒有意義的。做用域是如何造成的?函數在定義時會有個[[scope]]的內部屬性指向當時的做用域,一旦函數開始執行,它會建立一個新的做用域,而且用指針指向函數[[scope]]屬性指向的內容,如此就造成了一條做用域鏈,做用域鏈的最外層是全局做用域。編程語言
做用域鏈的做用就是作標示符解析。函數在執行時遇到變量標示符解析的時,首先從當前做用域查找,找不到則一直沿着做用域鏈向上搜索。做用域鏈會造成一個很是有意思的特性,叫閉包。就是外層函數執行完了(棧幀已經彈出),若是內層函數對象還沒被回收,外層做用域的變量環境會一直保留着,當內層函數執行的時候,依然能訪問外層做用域的變量環境。
javascript是一門很是面向對象的語言,對象的建立和使用極其方便。面向對象的4個特性裏面,封裝性的體現略差一點,因爲javascript是動態語言,討論多態性意義也不是很大。我的認爲面向對象主要是解決了兩大問題,一是以一個符合現實世界觀的方式組織抽象的代碼,二是解決複用的問題。前者先不作多討論,那是一種思惟方式和語言關係不大。後者在javascript裏的實現是很是有意思的。
能夠經過兩個方法來解釋對象的複用。假設有a、b兩個對象,b對象但願複用a對象的屬性和方法。一種作法是將a對象中全部的內容拷貝到b對象,這是Object.assign方法的功能。這種作法雖然很樸實,可是在一些簡單的複用場景是很是有用的。改方法的問題是會形成數據的冗餘,關係複雜的時候維護起來就很困難。另外一種作法是在b對象中保留一個指向a對象的指針。當我在訪問b對象的內容時,若是當前對象查不到,則沿着該指針繼續搜索下去。這是Object.create方法能達到如此效果。Object.create本質是利用了javascript原型鏈的特性。如何構造原型鏈?必須利用函數的另一個角色——構造器。當把new 操做符用到函數之上時,函數就發揮着構造器的角色。經過構造器構造對象時,其首先會建立一個空對象,而後將對象的原型指向構造器的prototype屬性,以此就能夠造成原型鏈了。javascript裏本質是沒有類的概念,Es6引入的class關鍵字只是個語法糖,本質仍是經過原型鏈實現繼承。
我的感受javascript裏的繼承更直接了當,直接從對象的角度去考慮複用,實際上是更接近現實的世界觀。
javascript還有個明顯的特色——單線程。javascript早期都是用做ui開發,單線程能夠比較好當規避同步問題,下降了ui開發門檻。單線程須要解決的是效率問題,javascript裏的解決思想是異步非阻塞。就是javascript主進程不要作耗時的事情,保證能快速執行快速相應,而將耗時的、io等待的事情交給其它進程去作。
在實現上javascript利用了一個事件循環和任務隊列,事件循環會不斷的檢查任務隊列有沒有須要處理的任務,有則立刻取出處理,無則等待。進入一個調用棧時,對於io操做通常是要當即返回,而把後續要作的事情放到任務隊列裏,這樣就不會形成io的阻塞。
正是單線程的特性,讓javascript在後端開發領域也火了一把。nodeJs讓javascript能夠跑在服務端後,對併發的支持有本身獨特的優點。
近些年javascript的應用愈來愈普遍,「任何可以用JavaScript實現的應用系統,最終都必將用JavaScript實現」的預言好像正在一步步變成現實。我的以爲ES六、ES七、ES8將這門語言變複雜和臃腫了。ES3其實就將最重要的基石肯定了。javascript有這麼強大的生命力,我的以爲主要緣由是其簡潔而強大,但願後面不要變得太臃腫。