1995年。誕生了JavaScript語言,那一年,我剛剛從大學畢業。在今年RedMonk 推出的2017 年第一季度編程語言排行榜中。JavaScript 排第一,Java 第二,Python 反超 PHP 排第三。PHP 第四,C# 和 C++ 並列第五。RedMonk 排名的主要依然是各類編程語言在 Stack Overflow 和 GitHub 上的表現,比方編程語言在 Stack Overflow 上的討論數量,在 GitHub 上的代碼量等。雖然有必定的片面性。仍是說明了JavaScript 應用的普遍性。從全棧的角度看,Javascript 是必備的一種編程語言。javascript
JavaScript 誕生於Netscape,但是在1996年。微軟公佈了與JavaScript 兼容的JScript,面對兼容和發展的需要。網景公司的先賢們努力增長了 ECMA International 標準化組織,致力於JavaScript 的標準化,命名爲ECMAScript。後來,由於歷史的緣由, JavaScript標準的開發主體變成了Mozila基金會。css
關於ECMAScript 的最新版本號可以參閱 https://tc39.github.io/ecma262/。html
簡單地,ECMAScript 是JavaScript語言的標準規範。就像C++的標準相對於C++語言那樣。前端
在mozilla 開發人員站點上是這樣描寫敘述JavaScript的:java
JavaScript (JS) is a lightweight interpreted or JIT-compiled programming language with first-class functions. node
意思是說JavaScript 是一個輕量級解釋或即時編譯的函數式語言。裏面有很是多的概念,輕量、解釋、編譯、即時編譯、函數式。git
在老碼農看來,簡單起見,理解爲擴展語言較爲方便。github
通常的編程語言都有着本身相對獨立的運行環境。但是JavaScript的運行環境依賴在宿主環境中。宿主環境尤爲是client的宿主環境提供了不少其它統一的環境變量,比方瀏覽器中的window。document等。實際上,JavaScript 和DOM 是可分的,對於不一樣的運行環境,有着不一樣的內置宿主對象。web
JavaScript做爲擴展語言在內置的宿主環境中運行,全局對象在程序啓動前就已經存在了。shell
從空間觀的角度看。JavaScript包含數據結構,操做符,語句與表達式。函數。從時間的角度看,包含做用域,處理方式,模塊與庫。關於技術系統的時空觀,可以參見《面向全棧的技術管理》一文。
JavaScript 中包含的六種基本類型:
Boolean
Null
Undefined
Number
String
Symbol (ECMAScript 6)
其它全是對象。
值是有類型的。變量是沒有類型的,類型定義了值的行爲特徵,變量在沒有持有值的時候是undefined。 JavaScript對值和引用的賦值/傳遞在語法上沒有差異,全然依據值的類型來斷定。
對於對象的屬性和方法而言,全局變量和全局函數是全局對象的屬性。全局對象至關於宿主對象的根對象。需要注意是屬性的屬性中那些不可變對象的實現方式:
對象常量: 結合writable和configurable:false 可以建立一個真正的常量屬性
禁止擴張:Object.preventExtensions(..)來禁止一個對象增長新屬性並保留已有屬性
密封: 在 Object.seal(..) 後不能增,刪,改 該屬性
凍結: Object.freeze(..) 會禁止對於對象自己及隨意直接屬性的改動
數據類型的斷定可以經過 contructor,instanceof。 isPrototypeOf等方法實現,對於鴨子類型的斷定還可以使用 in 的相關操做。符號並不是對象,而是一種簡單標量基本類型。
JavaScript 中的強制類型轉換老是返回基本類型值,將對象強制轉換爲String 是經過ToPrimitive抽象操做完畢的。而toJSON()是返回一個可以被字符串化的安全的JSON值。
操做符是空間元素鏈接的紐帶之中的一個,JavaScript操做符包含算術,鏈接,相等。比較。邏輯,位。類型推斷。條件。new,delete, void,"。", ".", "[]"等。
在JavaScript中以操做符進行操做每每都附帶着類型轉換。
一元運算符+ 是顯式強制類型轉換,而~是先轉換爲32位數字,而後按位反轉。
|| 和&& 更應該算是選擇器運算符。其返回值不必定是布爾值,而是兩個操做數當中的一個值。通常先對第一個操做數進行toBoolean強制類型轉換,而後再運行條件推斷。好比:a||b 理解成a?a:b 更通俗。對&& 而言,假設第一個是真值。則把第二個做爲返回值。a&&b 理解成a?
b:a 。
== 和=== 都會對操做數進行類型檢查。並運行隱性類型轉換,需要注意的是:
假設兩邊的值中有true或false,千萬不要使用==
假設兩邊有[],」」或者0。儘可能不要使用==
這裏是Github上關於各類相等性的矩陣:
操做符與變量/常量等鏈接造成了語句和表達式,好比表達式a+1中的null 被強制轉換爲0。
語句包含聲明與塊,控制語句有推斷。循環。break。continue,return,異常等。每個語句都有一個結果值。哪怕是undefined。
正則表達式是很是重要的一類表達式。主要使用RegExp類,運行方法test效率高,exec 會獲得一個結果對象的數組。
逗號運算符可以把多個獨立的表達式串聯成一個語句,{ }在不一樣狀況下的意思不盡相同,做爲語句塊,{ ..} 和for/while循環以及if條件語句中代碼塊的做用基本相同。
{a,b} 其實是{a:a,b:b}的簡化版本號。
try..catch..finally 中,假設finally中拋出異常。函數會在此處終止。需要注意的是,假設此前try中已經有return設置了返回值,則該值會被丟棄。finally中的return也會覆蓋try和catch中的return的返回值。
函數就是具備運算邏輯的對象,匿名函數不利於調試,回調函數是一種控制反轉。所有的函數(對象)都具備名爲prototype的屬性,prototype屬性引用的對象是prototype對象;所有的對象都含有一個隱式連接,用以指向在對象生成過程當中所使用的構造函數的prototype對象。
匿名函數沒有name 標識符,具備例如如下缺陷:
代碼更難理解
調試棧更難追蹤
自我引用(遞歸,事件(解除)綁定,等)更難
假設function是聲明的第一個詞,那就是函數聲明,不然就是函數表達式。立刻運行函數表達式形如:(function …)( )
時空密不可分,做用域是時空鏈接的紐帶之中的一個。做用域包含全局,函數。塊級做用域。做用域是依據名稱查找變量的一套規則。遍歷嵌套做用域鏈的規則簡單:引擎從當前運行做用域逐級向上查找。閉包可以理解爲具備狀態的函數。
函數做用域指屬於這個函數的所有變量都可以在整個函數的範圍內使用或複用。塊做用域形如 with。 try/catch。 ES6 引入了let,const等。
動態做用域並不關心函數和做用域是怎樣聲明以及在何處聲明的,僅僅關心它們從何處調用的。詞法做用域是定義在詞法分析階段的做用域。詞法做用域查找會在第一個匹配的標識符時中止。
做用域鏈是基於調用棧的。而不是代碼中的做用域嵌套。ReferenceError 是與做用域判別失敗相關。而TypeError則是做用域判別成功,但是對結果的操做非法或不合理。
this 提供了一種優雅方式來隱式「傳遞」一個對象引用。 this 即沒有指向函數的自身,也沒有指向函數的做用域。是在函數被調用時發生的綁定,它指向什麼全然取決於函數在哪裏被調用。假設分析this綁定的話,可以使用調試工具獲得調用棧。而後找到棧中的第二個元素,就是真正的調用位置。
this 的綁定規則有:
默認綁定:獨立的函數調用,嚴格模式不能將全局對象用於默認綁定
隱式綁定:把函數調用中的this 綁定到函數引用中的上下文對象
顯式綁定:經過call()和apply()方法可以直接指定this的綁定對象。
當中,硬綁定是一種顯式的強制綁定,ES5中提供了內置方法Function.prototype.bind, API中調用的上下文和bind的做用同樣。
new 綁定,構造函數僅僅是一些使用new操做符調用的函, 使用new 來調用函數的操做過程大體例如如下:
建立一個全新的對象
這個新對象會被運行[[Prototype]]連接
這個新對象會綁定到函數調用的this
假設函數沒有返回其它對象,那麼new表達式中的函數調用會本身主動返回這個新對象
假設同一時候存在多種綁定。那麼綁定的優先級大體例如如下:
由new調用綁定到新建立的對象
由call 或者apply(或bind)調用綁定到指定的對象
由上下文對象調用綁定到那個上下文對象
默認在在嚴格模式下綁定到undefined,不然綁定到全局對象
更安全地使用this 綁定的作法是傳入一個特殊的對象,把this 綁定到這個對象。需要注意的是。箭頭函數不使用this的4種規則,而是依據外層(函數或全局)做用域來決定this。
還要注意一點,eval 和 with 會致使做用域變化而引發性能降低,儘可能不要使用。
eval() 函數中的字符串是代碼,用來運行動態建立的代碼,嚴格模式有本身的做用域,還存在安全隱患;with 是反覆引用一個對象中的多個屬性的快捷方式,經過將一個對象的引用看成做用域來處理,會改變做用域範圍。
JavaScript引擎自己沒有時間概念。僅僅是一個按需運行隨意代碼片斷的環境,事件調度老是由包含它的宿主環境來運行。一旦有事件需要運行,事件循環隊列就會運行。直到隊列清空,用戶交互、IO和定時器等事件源會向事件隊列增長事件。
由於JavaScript的單線程特性,很是多函數的代碼具備原子性。
回調函數封裝了程序的延續性,常見設計是分離回調(一個用於成功通知,一個用於出錯通知)。還有一種回調模式是「error-first」,可能受到防護式編程的影響,NodeJS API 採用了此類的風格。假設成功的話,這個參數就會被清空。需要注意的是,回調函數的嵌套每每稱爲回調地獄。
Deferred是一種將異步處理串聯書寫並運行的機制,Deferred對象是一種具備unresolved,resolved,rejected 中某一種狀態的對象。
Deferred內部機制是先註冊回調函數,Deferred對象狀態發生變化時運行該函數。是一種提升代碼可讀性的機制。
Deferred對象的狀態遷移僅僅能發生一次,以then(),done(),fail(),always(),pipe()指定興許函數的方法。經過when()來並行處理,將Deferred 對象中的一部分方法刪除後獲得是Promise對象,對狀態的管理由最初建立該Deferred對象的所有者來運行。
Promise 封裝了依賴於時間的狀態,從而使得自己與時間無關。Promise 可以依照可預測的方式進行,而不用關心時序或底層的結果。一旦Promise決議完畢。就成爲了避免變值,可以安全地吧這個值傳遞給第三方,並確保不會改變。
Promise 是一種在異步任務中做爲兩個或不少其它步驟的流程控制機制,時序上的this-then-that。 不只表達了多步異步序列的流程控制。仍是一個從一個步驟到下一個步驟傳遞消息的消息通道。事件監聽對象可以當成是對promise 的一種模擬,對控制反轉的恢復實現了更好的關注點分離。
推斷是不是Promise 值的演示樣例代碼例如如下:
if( p !==null && ( typeof p ===「object」 || typeof p ===「function」) && typeof p.then===「function」) { console.log(「thenable」); } else{ console.log(「not thenable」); }
生成器是一類特殊的函數。可以一次或屢次啓動和中止,並不非的必定要完畢,生成器把while true 帶回了Javascript的世界。
當中,yield 託付的主要目的是代碼組織,以達到與普通函數調用的對稱。從生成器yield出一個Promise, 而且讓這個Promise 經過一個輔助函數恢復這個生成器。這是經過生成器管理異步的好方法之中的一個。
需要注意的是,假設在Promise.all([..]) 中傳入空數組,會立刻完畢, 而Promise.race([..]) 則會掛住。 在各類Promise庫中,finally ( .. ) 仍是會建立並返回一個新Promise的。
模塊和庫是JavaScript 時空中的還有一紐帶。提升了代碼的複用性和開發效率。
模塊充分利用了閉包的強大能力。從模塊中返回一個實際的對象並不是必須的。也可以直接返回一個內部函數,好比:jQauery 和 $標識符就是jQuery 模塊的公共API。
模塊有兩個必要條件:
必須有外部的封閉函數。該函數必須至少被調用一次
封閉函數必須返回至少一個內部函數,這樣內部函數才幹在私有做用域中造成閉包,而且可以訪問或改動私有的狀態
import 可以將一個模塊的一個或多個API導入到當前做用域中。並分別綁定在一個變量上;module 則將整個模塊的API 導入並綁定到一個變量上, export 將當前模塊的一個標識符導出爲公共API。
大多數模塊所依賴的加載器/管理器本質上是將這種模塊定義封裝進一個API。基於函數的模塊並不是一個能被靜態識別的模式(編譯器),API定義僅僅有在運行時考慮進來。
但是ES6 模塊的API 是靜態的,必須被定義在獨立的文件裏。
JavaScript 中的庫浩如煙海,這裏僅對JQuery作簡要說明。JQuery壓縮後大約31k,輕巧靈活,經過鏈式語法實現邏輯功能。經過CSS3選擇器及本身定義選擇器獲取元素,支持插件。可擴展性高。
JQuery中 的特點函數——$ ,可以抽取與選擇器匹配的元素,或者建立新的DOM元素,將已有的DOM元素轉換爲jQuery對象,對DOM構造完畢後的事件監聽器進行設定等等。JQuery 對DOM,樣式,AJAX 都可有效處理。
經過擴展JQuery.fn 就可以建立JQuery的插件,code.google.com/apis/libraries 給出了很是多JQuery 的插件信息。
利用JavaScript 的時空觀,可以對這一語言有一些主要的梳理。就語言自己而言。keyword是不能迴避的,對JavaScript keyword,在StackOverFlow中有人給出了例如如下詩同樣的總結:
Let this long package float, Goto private class if short。 While protected with debug case, Continue volatile interface。Instanceof super synchronized throw。 Extends final export throws. Try import double enum?
-False, boolean, abstract function. Implements typeof transient break! Void static,default do, Switch int native new, else, delete null public var, In return for const, true, char, …… finally catch byte.
一門語言所被使用的普遍程度取決於使用的場景,正如PHP被普遍採用那樣,互聯網應用不只是JavaScript 的家鄉,而且是它大展身手的最重要場所,沒有JavaScript 的Web應用差點兒絕跡了。
web應用中使用JavaScript有拖拽操做。異步讀取。鍵盤訪問 和動畫效果等基本功能。對於清晰地使用JavaScript實現Web應用而言。理解瀏覽器網頁處理過程是必要的。
通常地,瀏覽器先分析HTML。而後構造DOM樹。再加載外部Javascript 文件以及CSS文件,接下來加載圖像文件等外部資源。最後在分析Javascript後開始運行至所有完畢。
在HTML中加載JavaScript的方式有多種:
<script> 標籤。在body 結束標籤前寫
讀取外部JavaScript 文件,讀取完就開始運行,瀏覽器可以緩存
onload 事件加載
DOMContentLoaded是在完畢HTML解析後發生的事件,也可以用於加載JavaScript
動態加載。這樣JS在加載時不會阻斷其它操做,如
var script = document.createElement(‘script’);
script.src = ‘my-javascript.js’;
document.getElementsByTagName(‘head’)[0].appendChild(script)
window對象是JavaScript所能操做的最高層對象,當中的屬性包含navigator,location,history,screen,frames。document,parent,top。self 等。
DOM 是一種API。完畢對HTML/XML 的樹形結構訪問。如標籤,元素。節點等。節點可以經過ID。標籤名。名稱和類名進行檢索。好比:
var element = document.getElementById(「abel」) var allelements = document.getElementByTagName(‘*’)
由於返回的是NodeList對象,性能較差。可以經過 var array = Array.prototye.slice.call(allelements)
轉換爲array 後處理。
節點的訪問可以經過XPath 進行靈活的訪問,固然,Selector API 比XPath更簡單且相同靈活。好比:
var a_label = document.querySelector(‘#abel’) var b_all = document.querySelectorAll(‘div’)
假設先改動DocumentFragment。再對實際的document對象操做。DOM 的操做性能會較高一些。
事件偵聽器的設定可以制定HTML元素的屬性。也可以指定DOM元素的屬性。還可以經過EventTarget.addEventListenser()進行指定。事件的處理包含捕獲。目標處理和事件冒泡三個階段。捕獲的過程是:
window -> document -> html -> body -> div -> button
而後處理器運行,冒泡向上傳播的過程是遍歷DOM樹,需要注意的是 focus 不會冒泡。
DOM2中的標準事件有HTMLEvent,MouseEvent。UIEvent和MutationEvent。DOM3 中的事件不少其它:UIEvent,FocusEvent,MouseEvent, WheelEvent, TextEvent,KeyboardEvent 和compositionEvent等,還可以通document.createEvent來本身定義事件。
經過JavaScript 對CSS樣式變動的方法有經過className 屬性變動class名,經過classList屬性更改class名(當中classList 是H5對DOM TokenList接口的實現),還可以更改Style 屬性或者直接更改樣式表。經過JavaScript可以對屏幕位置(screenX。screenY),窗體位置(clientX,clientY)。文檔座標(pageX。pageY。由瀏覽器自行實現的),特定元素內的相對位置(layerX,layerY 或offsetX offsetY)進行改動。
經過JavaScript可以對錶單中的元素,控件和內容進行驗證,可用於驗證的事件有submit,focus。blur,change,keydown/up/press。input。使用表單而不產生頁面跳轉的方式可以是指向到一個 (0,0 )的空iframe。
對於動畫而言。css的動畫性能通常要更好一些。
AJAX 在Web應用中是不可或缺的。簡單地說,是一種不發生頁面跳轉就能異步加載內容並改寫頁面內容的技術。主要經過 XMLHttpRequest 對象的建立,實現通/異步通訊,處理超時和響應。AJAX有着跨源限制,實現跨源通訊的方式有:JSONP。iframe hack,window.postMessage() 以及 XMLHttpRequest Level 2。
HTML5+CSS3+JavaScript的綜合使用纔可能成就一個Web應用。
H5中的 History API 使用了window屬性的history對象監聽popstate事件。用於恢復頁面狀態的處理。ApplicationCache 在html標籤的manifest 屬性中指定了緩存清單文件的路徑,必須經過text/cache-manifest 這一MIME type 來公佈緩存清單文件。注意清單中的CACHE,NETWORK,和FALLBACK 的區分。
經過navigator.onLine 可以獲知網絡狀態,還可以經過online/offline事件來偵聽鏈接狀態的切換時機。
online/offline事件是document.body 觸發的,並傳給document對象和window對象。
<p> network is : <span id = 「indicator」> (state unknown) </span> </p> <script> { function updateIndicator = document.getElementById(‘indicator’); indicator.textContext = navigator.online?’online’:’offline’; } document.body.onload = updateIndicator; document.body.ononline= updateIndicator; document.body.onoffline = updateIndicator; </script>
DataTransfer 是Drag Drop API 的核心,在所有拖拽事件的事件對象中,都有該屬性,主要是接收數據。
拖拽文件從瀏覽器保存到桌面:event.dataTransfer.setData(‘DownloadURL’,’MIMETYPE: 文件url’)
好比:
<a href=「http://a.b.c/abel.pdf」 data-downloadurl = 「application/pdf:abel.pdf:http://a.b.c/abel.pdf」 class=「dragout」 draggable = 「true」>download </a> <script> var files = document.querySelectorAll(‘.dragout’); for (var i = 0,file; file =files[i];i++) { file.addEventListener(‘dragstart’,function(event){ event.dataTransfer.setData(「DownloadURL」,this.dataset.downloadurl); },false); } </script>
FileAPI 經過FileReader 讀取文件,也可以讀取dataURL。FileReaderSync 用於同步讀取文件內容,可以在Web Worker 中使用。
Web Storage 爲所有源共享5M空間。localStorage 和sessionStorage 的差異在於數據的生命週期。cookie 最大4k,發請求時一塊兒發送,保存會話等重要信息。
indexedDB 可以歸爲文檔型數據庫, 做爲client存儲又一選擇。
var indexdb = window.indexDB||window.webkitIndexedDB||window.mozIndexedDB;
Web worker 是H5 的新特性,是宿主環境(瀏覽器)的功能,JavaScript 自己是不支持多線程的。專用的worker 與建立它的程序之間是一對一的關係。
Web worker 能在另外的線程中建立新的Javascript 運行環境,使JavaScripts可以在後臺處理。主線程和工做線程分離。沒法使用對方環境的變量。工做線程沒法引用document對象,需要經過消息收發完畢數據傳遞。 在主線程建立工做線程。大約向var worker = new Worker(‘work.js’)這樣
在主線程中中止worker的方式是worker.terminate();
worker 自身中止的方式是 self.close();
worker 中 可以通個 importScripts 方法,在工做線程內讀取外部的文件。
瞭解了這些基礎方式和方法,僅僅是Web應用中JavaScript開發的第一步吧。
技術系統老是又着向超系統進化的趨勢。JavaScript 也不例外。
JavaScript 應用於服務端的開發源於2009年初出現的CommonJS,後來成爲爲了server端javaScript的規範。基於JavaScript沒有模塊系統、標準庫較少、缺少包管理工具等現狀,CommonJS規範但願JavaScript可以在不論什麼地方運行,以達到Java、C#、PHP這些後臺語言具有開發大型應用的能力。
CommonJS是一種思想,它的終極目標是使應用程序開發人員依據CommonJS API編寫的JavaScript應用可以在不一樣的JavaScript解析器和HOST環境上運行。好比編寫服務端應用。命令行工具。基於GUI的桌面應用和混合應用編程等,詳情參加 www.commonjs.org 。
NodeJS可以理解成CommonJS規範的一種實現。而且是部分實現。NodeJS以V8做爲JavaScript的實現引擎,通用的異步處理事件循環,提供了一系列非堵塞函數庫來支持實踐循環特性。同一時候。NodeJS提供了高度優化的應用庫。來提升server效率,好比其http 模塊是爲高速非堵塞式http服務而用C語言重寫的。另外,NodeJS還有shell的命令行工具,經過包系統實現擴展,擴展列表可以詳情參見: GitHub.com/node/wiki/modules。
JavaScript 中的主要實現引擎包含:IE採用的JScript,Firefox採用的SpiderMoneky。Chrome 採用的V8,Safari採用的webkit中的 javacriptcore燈。假設要對引擎有進一步的瞭解,可以研讀一下javascriptcore等相關的源碼。
V8 是NodeJS 中的核心引擎。NodeJS的系統架構大體例如如下:
與瀏覽器相相應。Node 中的全局變量可以經過 Object.keys(global);
得到。 看一看NodeJS中的 「hello world」 程序:
var http = require('http'); http.createServer(function (req,res){ res.writeHead(200,{'Content-type':'text/plain'}); res.end('Hello Node.js \n'); }).listen(1234,"127.0.0.1"); console.log('Server running on http://127.0.0.1:1234/');
幾行代碼就實現一個簡單web server。 使Pythoner 們聯想到了 Tornado, 它們都走在單線程異步IO的路上。
NodeJS 提供了對https 的支持,可以經過openssl 生成證書的方式大體是:
openssl req -new -x509 -keyout key.pen -out cert.perm
使用證書的示比例如如下:
var fs =require(‘fs’); var options = { key: fs.readFileSync(‘key.perm’); cert:fs.readFileSync(‘cert.perm’); }
NodeJS支持socket 和文件處理,配合系統擴展可以使用各類模版語言。
基於NodeJS的實際在業界很是普遍,比方面向websocket的IM系統,各類web應用站點等等。
鑑於微服務架構的興起。也誕生了基於Node的微服務架構——Seneca。它使用完備的模式匹配接口來鏈接各個服務,從代碼中將傳輸數據抽象出來。使編寫具備高擴展性的軟件變得至關easy。
Seneca 沒有使用依賴注入,但是在處理控制反轉上至關靈活,沒有keyword和強制的字段。僅僅需一組鍵值對。用於模式匹配的引擎中。詳細參考實現,可以參考《node.js 微服務》一書。
假設在整個應用系統中主要使用JavaScript編程語言做爲技術棧,那麼也可以成爲基於JavaScript 的全棧,關於全棧的論述可以參加《全棧的技術棧設想》和《再談< 全棧架構師>》兩篇文字。
好比MEAN架構。即MongoDB + Express + Angular + Node,MEAN 技術棧表明着一種全然現代的 Web 開發方法:一種語言運行在應用程序的所有層次上,從client到server,再到持久層。
藉助JavaScript的測試框架。比方MochaJS、JasmineJS 和 KarmaJS,可以爲本身的 MEAN 應用程序編寫深刻而又全面的測試套件,據說MEAN有代替LAMP/LNMP的的趨勢。但還需保持慎重。
正像Java 那樣。雖然又着虛擬機規範。但各個JVM的實現仍是有着些許的不一樣,JavaScript 也是如此。JavaScript各引擎中相同存在着少許的限制,好比:
字符串常量中贊成的最大字符數
做爲參數傳遞到函數中的數據大小(棧大小)
函數聲明中的參數個數
函數調用鏈的最大長度
以堵塞方式在瀏覽器中運行的最大時間
變量名的最大長度
雖然如此,JavaScript 在瀏覽器中的表現仍是基本上可信的。
實際上,JavaScript已經嵌入到了從機器人到各類家電等各類各樣的設備中。這裏隆重推薦我很是敬佩的好友——周愛民老師,他在Ruff(南潮信息科技)作的事情就是JavaScript 在物聯網上的進一步應用。
Ruff 是一個可以讓開發人員實現敏捷開發智能硬件的系統平臺。它包含了Ruff SDK、Ruff OS。Rap Registry等。從技術上講,Ruff 是一個 JavaScript 運行時,專爲硬件開發而設計。
Ruff 對硬件進行了抽象,使用了基於事件驅動、異步 I/O 的模型,使硬件開發變得輕量而且高效。硬件抽象層,使得操做硬件宛如普通程序庫,減小了硬件領域進入門檻。
Ruff 爲開發人員提供了無缺的開發服務。
從項目生產、軟件包管理、應用管理、外設管理到固件管理等一系列現代軟件開發方式。PC 端完畢開發,無需燒板子。提高開發人員的開發效率。
Ruff 還提供了無缺的測試框架,支持 assert、test、mock 等模塊,在開發機上測試邏輯,硬件測試也能 TDD。
官網(ruff.io) 上給出的示比例如如下:
$.ready(function() { $('#led-0').turnOn(); });
打開電路板上的一個LED 燈,就是如此的簡單。
眼下,一個 Ruff 硬件同一時候僅僅能運行一款 Ruff 應用,它將擁有本身獨立的進程。着可能也受到JavaScript自身的限制吧。
性能是全棧關注的一個重要維度。那句「過早優化是萬惡之源」其實是咱們對高德納先生的斷章取義,原文是這種:
咱們應該在好比97%的時間裏,忘掉小處的效率;
過早優化是萬惡之源。
但咱們不該該錯過關鍵的3%中的機會。
其實是非關鍵路徑上的優化是萬惡之源,問題在於怎樣肯定咱們的代碼是否在關鍵路徑上。
不論節省的時間多麼少,花費在關鍵路徑上的性能優化都是值得的。
對於性能優化工具,用於JavaScript源碼壓縮有 google Closure complier。packer。YUI compressor,JSmin等。頁面的性能優化工具備YSlow 和Page Speed等。
實際上。不論什麼有意義且可靠的性能測試都是基於統計學上的合理實踐。 就JavaScript 代碼自己的性能而言,benchmarkjs 是一個很是好的工具,而jsperf.com 提供了對JavaScript 運行環境的性能測試。
總之,JavaScript 是一個具備強大生命力的語言,前端框架更是突飛猛進。從Angular。Vue。到React, 乃至React Native,給人以應接不暇的感受,但是,老碼農認爲基礎認識仍是很是必要的,勿在浮沙築高塔。
https://developer.mozilla.org/en-US/docs/Web/JavaScript
https://tc39.github.io/ecma262/#sec-global-object
微信掃一掃關注該公衆號