精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

全棧必備JavaScript基礎

開發 開發工具
JavaScript 是一個具有強大生命力的語言,前端框架更是日新月異,從Angular,Vue,到React, 乃至React Native,給人以目不暇接的感覺,但是,老碼農覺得基礎認識還是非常必要的,勿在浮沙筑高塔。

[[187649]]

1995年,誕生了JavaScript語言,那一年,我剛剛從大學畢業。在今年RedMonk 推出的2017 年第一季度編程語言排行榜中,JavaScript 排第一,Java 第二,Python 反超 PHP 排第三,PHP 第四,C# 和 C++ 并列第五。RedMonk 排名的主要依舊是各種編程語言在 Stack Overflow 和 GitHub 上的表現,比如編程語言在 Stack Overflow 上的討論數量,在 GitHub 上的代碼量等。盡管有一定的片面性,還是說明了JavaScript 應用的廣泛性。從全棧的角度看,Javascript 是必備的一種編程語言。

 

ECMAScript 和 JavaScript 的關系

JavaScript 誕生于Netscape,但是在1996年,微軟發布了與JavaScript 兼容的JScript,面對兼容和發展的需要,網景公司的先賢們努力加入了 ECMA International 標準化組織,致力于JavaScript 的標準化,命名為ECMAScript。后來,由于歷史的原因, JavaScript標準的開發主體變成了Mozila基金會。

簡單地,ECMAScript 是JavaScript語言的標準規范,就像C++的標準相對于C++語言那樣。

JavaScript 是怎樣的語言

在mozilla 開發者網站上是這樣描述JavaScript的:

JavaScript (JS) is a lightweight interpreted or JIT-compiled programming language with first-class functions.

意思是說JavaScript 是一個輕量級解釋或即時編譯的函數式語言,里面有很多的概念,輕量、解釋、編譯、即時編譯、函數式。在老碼農看來,簡單起見,理解為擴展語言較為方便。

一般的編程語言都有著自己相對獨立的執行環境,但是JavaScript的執行環境依賴在宿主環境中,宿主環境尤其是客戶端的宿主環境提供了更多統一的環境變量,比如瀏覽器中的window,document等。實際上,JavaScript 和DOM 是可分的,對于不同的運行環境,有著不同的內置宿主對象。JavaScript作為擴展語言在內置的宿主環境中運行,全局對象在程序啟動前就已經存在了。

JavaScript的時空基礎

從空間觀的角度看,JavaScript包括數據結構,操作符,語句與表達式,函數;從時間的角度看,包括作用域,處理方式,模塊與庫。

數據結構

JavaScript 中包含的六種基本類型:

  • Boolean
  • Null
  • Undefined
  • Number
  • String
  • Symbol (ECMAScript 6)

其它全是對象。值是有類型的,變量是沒有類型的,類型定義了值的行為特征,變量在沒有持有值的時候是undefined。 JavaScript對值和引用的賦值/傳遞在語法上沒有區別,完全根據值的類型來判定。

對于對象的屬性和方法而言,全局變量和全局函數是全局對象的屬性,全局對象相當于宿主對象的根對象。需要注意是屬性的屬性中那些不可變對象的實現方式:

  1. 對象常量: 結合writable和configurable:false 可以創建一個真正的常量屬性
  2. 禁止擴張:Object.preventExtensions(..)來禁止一個對象添加新屬性并保留已有屬性
  3. 密封: 在 Object.seal(..) 后不能增,刪,改 該屬性
  4. 凍結: 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 標識符,具有如下缺陷:

  1. 代碼更難理解
  2. 調試棧更難追蹤
  3. 自我引用(遞歸,事件(解除)綁定,等)更難

如果function是聲明的第一個詞,那就是函數聲明,否則就是函數表達式。立即執行函數表達式形如:(function …)( )

時空密不可分,作用域是時空連接的紐帶之一。作用域包括全局,函數,塊級作用域。作用域是根據名稱查找變量的一套規則,遍歷嵌套作用域鏈的規則簡單:引擎從當前執行作用域逐級向上查找。閉包可以理解為具有狀態的函數。

函數作用域指屬于這個函數的全部變量都可以在整個函數的范圍內使用或復用。塊作用域形如 with, try/catch, ES6 引入了let,const等。

動態作用域并不關心函數和作用域是如何聲明以及在何處聲明的,只關心它們從何處調用的。詞法作用域是定義在詞法分析階段的作用域,詞法作用域查找會在第一個匹配的標識符時停止。作用域鏈是基于調用棧的,而不是代碼中的作用域嵌套。ReferenceError 是與作用域判別失敗相關,而TypeError則是作用域判別成功,但是對結果的操作非法或不合理。

this 提供了一種優雅方式來隱式“傳遞”一個對象引用。 this 即沒有指向函數的自身,也沒有指向函數的作用域,是在函數被調用時發生的綁定,它指向什么完全取決于函數在哪里被調用。如果分析this綁定的話,可以使用調試工具得到調用棧,然后找到棧中的第二個元素,就是真正的調用位置。

this 的綁定規則有:

  1. 默認綁定:獨立的函數調用,嚴格模式不能將全局對象用于默認綁定
  2. 隱式綁定:把函數調用中的this 綁定到函數引用中的上下文對象
  3. 顯式綁定:通過call()和apply()方法可以直接指定this的綁定對象。其中,硬綁定是一種顯式的強制綁定,ES5中提供了內置方法Function.prototype.bind, API中調用的上下文和bind的作用一樣。
  4. new 綁定,構造函數只是一些使用new操作符調用的函, 使用new 來調用函數的操作過程大致如下:
  • 創建一個全新的對象
  • 這個新對象會被執行[[Prototype]]鏈接
  • 這個新對象會綁定到函數調用的this
  • 如果函數沒有返回其他對象,那么new表達式中的函數調用會自動返回這個新對象

如果同時存在多種綁定,那么綁定的優先級大致如下:

  1. 由new調用綁定到新創建的對象
  2. 由call 或者apply(或bind)調用綁定到指定的對象
  3. 由上下文對象調用綁定到那個上下文對象
  4. 默認在在嚴格模式下綁定到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 值的示例代碼如下:

  1. if( 
  2.     p !==null && 
  3.     ( typeof p ===“object” || typeof p ===“function”) && typeof p.then===“function”) 
  4.     { 
  5.         console.log(“thenable”); 
  6.     } 
  7. else
  8.     console.log(“not thenable”); 

生成器是一類特殊的函數,可以一次或多次啟動和停止,并不非的一定要完成,生成器把while true 帶回了Javascript的世界。其中,yield 委托的主要目的是代碼組織,以達到與普通函數調用的對稱。從生成器yield出一個Promise, 并且讓這個Promise 通過一個輔助函數恢復這個生成器,這是通過生成器管理異步的好方法之一。

需要注意的是,如果在Promise.all([..]) 中傳入空數組,會立即完成, 而Promise.race([..]) 則會掛住。 在各種Promise庫中,finally ( .. ) 還是會創建并返回一個新Promise的。

模塊與庫

模塊和庫是JavaScript 時空中的另一紐帶,提高了代碼的復用性和開發效率。

模塊充分利用了閉包的強大能力,從模塊中返回一個實際的對象并不是必須的,也可以直接返回一個內部函數,例如:jQauery 和 $標識符就是jQuery 模塊的公共API。

模塊有兩個必要條件:

  1. 必須有外部的封閉函數,該函數必須至少被調用一次
  2. 封閉函數必須返回至少一個內部函數,這樣內部函數才能在私有作用域中形成閉包,并且可以訪問或修改私有的狀態

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 的時空觀,可以對這一語言有一些基本的梳理。就語言本身而言,關鍵字是不能回避的,對JavaScript 關鍵字,在StackOverFlow中有人給出了如下詩一樣的總結:

  1. Let this long package float, 
  2. Goto private class if short。 
  3. While protected with debug case, 
  4. Continue volatile interface。 
  5. Instanceof super synchronized throw, 
  6. Extends final export throws. 
  7.  
  8. Try import double enum? 
  9. -False, boolean, abstract function
  10. Implements typeof transient break! 
  11. Void static,default do, 
  12. Switch int native new, 
  13. elsedelete null public var, 
  14. In return for const, truechar
  15. …… 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在載入時不會阻斷其他操作,如
  1. var script = document.createElement(‘script’); 
  2. script.src = ‘my-javascript.js’; 
  3. document.getElementsByTagName(‘head’)[0].appendChild(script) 

window對象是JavaScript所能操作的最高層對象,其中的屬性包括navigator,location,history,screen,frames,document,parent,top,self 等。

DOM 是一種API,完成對HTML/XML 的樹形結構訪問,如標簽,元素,節點等。節點可以通過ID,標簽名,名稱和類名進行檢索,例如:

  1. var element = document.getElementById(“abel”)  
  2. var allelements = document.getElementByTagName(‘*’) 

由于返回的是NodeList對象,性能較差,可以通過 var array = Array.prototye.slice.call(allelements)轉換為array 后處理。節點的訪問可以通過XPath 進行靈活的訪問,當然,Selector API 比XPath更簡單且同樣靈活,例如:

  1. var a_label = document.querySelector(‘#abel’)  
  2. var b_all = document.querySelectorAll(‘div’) 

如果先修改DocumentFragment,再對實際的document對象操作,DOM 的操作性能會較高一些。

事件偵聽器的設定可以制定HTML元素的屬性,也可以指定DOM元素的屬性,還可以通過EventTarget.addEventListenser()進行指定。事件的處理包括捕獲,目標處理和事件冒泡三個階段,捕獲的過程是:

  1. 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對象。

  1. <p> network is : <span id = “indicator”> (state unknown) </span> </p> 
  2. <script> 
  3.     function updateIndicator = document.getElementById(‘indicator’); 
  4.     indicator.textContext = navigator.online?’online’:’offline’; 
  5. document.body.onload = updateIndicator; 
  6. document.body.ononline= updateIndicator; 
  7. document.body.onoffline = updateIndicator; 
  8. </script> 

DataTransfer 是Drag Drop API 的核心,在所有拖拽事件的事件對象中,都有該屬性,主要是接收數據。拖拽文件從瀏覽器保存到桌面:event.dataTransfer.setData(‘DownloadURL’,’MIMETYPE: 文件url’)例如:

  1. <a href=“http://a.b.c/abel.pdf”  
  2.    data-downloadurl = “application/pdf:abel.pdf:http://a.b.c/abel.pdf” 
  3.    class=“dragout” draggable = “true”>download </a> 
  4.    <script> 
  5.    var files = document.querySelectorAll(‘.dragout’); 
  6.    for (var i = 0,file; file =files[i];i++) { 
  7.        file.addEventListener(‘dragstart’,function(event){ 
  8.    event.dataTransfer.setData(“DownloadURL”,this.dataset.downloadurl); 
  9.    },false); 
  10.    } 
  11.    </script> 

FileAPI 通過FileReader 讀取文件,也可以讀取dataURL,FileReaderSync 用于同步讀取文件內容,可以在Web Worker 中使用。

Web Storage 為所有源共享5M空間,localStorage 和sessionStorage 的區別在于數據的生命周期。cookie 最大4k,發請求時一起發送,保存會話等重要信息。indexedDB 可以歸為文檔型數據庫, 作為客戶端存儲又一選擇。

  1. 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,后來成為為了服務器端javaScript的規范。基于JavaScript沒有模塊系統、標準庫較少、缺乏包管理工具等現狀,CommonJS規范希望JavaScript可以在任何地方運行,以達到Java、C#、PHP這些后臺語言具備開發大型應用的能力。CommonJS是一種思想,它的終極目標是使應用程序開發者根據CommonJS API編寫的JavaScript應用可以在不同的JavaScript解析器和HOST環境上運行,例如編寫服務端應用,命令行工具,基于GUI的桌面應用和混合應用編程等,詳情參加 www.commonjs.org 。

[[187650]]

NodeJS可以理解成CommonJS規范的一種實現,而且是部分實現。NodeJS以V8作為JavaScript的實現引擎,通用的異步處理事件循環,提供了一系列非阻塞函數庫來支持實踐循環特性。同時,NodeJS提供了高度優化的應用庫,來提高服務器效率,例如其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” 程序:

  1. var http = require('http'); 
  2. http.createServer(function (req,res){ 
  3.     res.writeHead(200,{'Content-type':'text/plain'}); 
  4.     res.end('Hello Node.js \n'); 
  5. }).listen(1234,"127.0.0.1"); 
  6. console.log('Server running on http://127.0.0.1:1234/'); 

幾行代碼就實現一個簡單web server, 使Pythoner 們聯想到了 Tornado, 它們都走在單線程異步IO的路上。

NodeJS 提供了對https 的支持,可以通過openssl 生成證書的方式大致是:

  1. openssl req -new -x509 -keyout key.pen -out cert.perm 

使用證書的示例如下:

  1. var fs  =require(‘fs’); 
  2. var options = { 
  3.     key: fs.readFileSync(‘key.perm’); 
  4.     cert:fs.readFileSync(‘cert.perm’); 

NodeJS支持socket 和文件處理,配合系統擴展可以使用各種模版語言。基于NodeJS的實際在業界非常廣泛,比如面向websocket的IM系統,各種web應用網站等等。

鑒于微服務架構的興起,也誕生了基于Node的微服務架構——Seneca,它使用完備的模式匹配接口來連接各個服務,從代碼中將數據傳輸抽象出來,使編寫具有高擴展性的軟件變得相當容易。Seneca 沒有使用依賴注入,但是在處理控制反轉上相當靈活,沒有關鍵字和強制的字段,只需一組鍵值對,用于模式匹配的引擎中。具體參考實現,可以參考《node.js 微服務》一書。

基于JavaScript的全棧

如果在整個應用系統中主要使用JavaScript編程語言作為技術棧,那么也可以成為基于JavaScript 的全棧,關于全棧的論述可以參加《全棧的技術棧設想》和《再談< 全棧架構師>》兩篇文字。例如MEAN架構,即MongoDB + Express + Angular + Node,MEAN 技術棧代表著一種完全現代的 Web 開發方法:一種語言運行在應用程序的所有層次上,從客戶端到服務器,再到持久層。借助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) 上給出的示例如下:

  1. $.ready(function() { 
  2.    $('#led-0').turnOn(); 
  3. }); 

打開電路板上的一個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,給人以目不暇接的感覺,但是,老碼農覺得基礎認識還是非常必要的,勿在浮沙筑高塔。

【本文來自51CTO專欄作者“老曹”的原創文章,作者微信公眾號:喔家ArchiSelf,id:wrieless-com】

戳這里,看該作者更多好文

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2020-07-20 08:23:04

Redis分布式系統

2021-06-01 07:16:21

C語言基礎代碼

2017-06-13 08:55:29

Log日志MySQL

2017-06-13 15:10:02

大數據Log日志

2017-10-12 14:24:24

2013-12-09 09:42:50

JavaScript全棧式

2017-12-18 15:33:56

Java基礎編程

2023-12-10 20:30:51

SQL工具數據

2017-08-07 13:02:32

全棧必備貝葉斯

2017-04-12 14:45:20

數據架構數據源

2018-01-09 15:35:54

Python編程基礎

2022-07-06 11:21:11

JHipsterJavaJavaScript

2015-08-17 09:27:51

全棧工程師Devops工具周期表

2018-10-15 10:22:51

2019-06-05 13:30:24

ReactJavaScript開發

2023-08-21 09:51:57

全棧軟件開發

2015-05-04 09:23:38

JavaScript全棧開發員云計算

2017-11-10 19:00:37

華為

2023-07-03 00:47:23

2017-07-05 11:09:35

華為開發云
點贊
收藏

51CTO技術棧公眾號

精品在线视频免费观看| 日本精品一区二区三区四区| 国产又大又黑又粗| 欧美日韩免费| 亚洲黄色av女优在线观看| 欧美深夜福利视频| av在线电影免费观看| 国内外成人在线| 欧美精品久久久久久久| 成都免费高清电影| 电影91久久久| 黄网站色欧美视频| 杨幂一区欧美专区| 噜噜噜久久,亚洲精品国产品| 男女av一区三区二区色多| 国产精品久久久久久久久免费相片 | 99re8这里有精品热视频免费| 黑人巨大精品欧美一区二区一视频| 日韩色妇久久av| 亚洲国产成人在线观看| 日本系列欧美系列| 97国产suv精品一区二区62| 亚洲色图日韩精品| 日韩欧美ww| 日韩欧美电影一区| 在线观看国产中文字幕| 天堂av在线| 亚洲综合视频在线观看| 亚洲7777| 色视频在线观看福利| 国产一区二区精品久久99| 国产成人综合av| 天天操天天爽天天干| 欧美伊人久久| 视频在线一区二区| 久久久久久亚洲中文字幕无码| 亚洲精品视频一二三区| 欧美精品日韩一区| 免费看a级黄色片| 手机av在线| 一区二区三区资源| 国产盗摄视频在线观看| 在线免费观看黄色网址| 国产农村妇女毛片精品久久麻豆| 久久精品成人一区二区三区蜜臀| 亚洲精品一区二区三区四区| 国产自产视频一区二区三区| 国产精品一区二区久久精品| 国产又粗又猛又黄视频| 久久国产66| 高清欧美电影在线| 久久精品视频久久| 国产综合精品一区| 久久久久久久色| 欧美精品入口蜜桃| 欧美日本中文| 欧美激情一级二级| 国产精品99精品无码视| 亚洲国产免费| 2018中文字幕一区二区三区| 国产精品suv一区二区三区| 亚洲黄色av| 午夜精品在线观看| 日本高清不卡码| 另类激情亚洲| 国产精品久久久久久久av电影| 国产精品熟女视频| 男人的j进女人的j一区| 成人在线播放av| www.天天干.com| 成人免费视频免费观看| 精品产品国产在线不卡| 亚洲av成人精品日韩在线播放| 成人av资源在线| 精品一区国产| 国内精品在线视频| 中文字幕一区二| 无码毛片aaa在线| 国产盗摄在线视频网站| 偷拍一区二区三区| 凹凸日日摸日日碰夜夜爽1| 久久夜夜操妹子| 欧美日韩电影一区| 久久久久亚洲av无码专区首jn| 久久久久观看| 国产亚洲免费的视频看| 欧美xxxooo| 狠狠久久婷婷| 国产激情久久久久| 国产三级三级在线观看| av不卡免费在线观看| 日韩资源av在线| 国产激情在线| 精品国产乱码久久久久久虫虫漫画 | 首页国产精品| 久久久久免费视频| 伊人久久中文字幕| 国产精品18久久久久久久久| 久久久久一区二区三区| 日本三级在线视频| 午夜精品久久久久久久久| 欧美一级黄色影院| 精品麻豆剧传媒av国产九九九| 日韩va亚洲va欧洲va国产| 91社区视频在线观看| 国产综合精品| 国产精品人成电影在线观看| 韩国av免费在线观看| 国产日本亚洲高清| 欧美亚洲黄色片| 欧美黄页在线免费观看| 亚洲精品久久久久久久久久久久 | 日韩福利视频一区| 久久精品美女视频网站| 五月天婷婷导航| 粉嫩av亚洲一区二区图片| 日韩中文字幕av在线| 久久青草伊人| 日韩美女视频在线| 岛国片在线免费观看| 国产一区二区高清| 1卡2卡3卡精品视频| 国产视频在线看| 午夜精品视频在线观看| 日本精品一区在线| 欧美精品一区二区三区中文字幕| 午夜精品理论片| www.精品久久| 自拍偷拍国产亚洲| 激情五月俺来也| 国产成人一区| 欧美性受xxx| 欧美特黄一级视频| 亚洲自拍偷拍图区| 日韩精品视频网址| 国产精品99久久| 国产欧美日韩免费| 福利在线视频导航| 欧美性高跟鞋xxxxhd| 88av在线播放| 精品电影一区| 操一操视频一区| 国产剧情在线| 51精品秘密在线观看| 久久久久人妻一区精品色| 日韩黄色小视频| 日本亚洲欧洲精品| 666av成人影院在线观看| 亚洲精品综合精品自拍| 久久久国产精品成人免费| 不卡av在线免费观看| 三上悠亚久久精品| 台湾色综合娱乐中文网| 欧美在线日韩在线| 久青草国产在线| 在线看国产日韩| www中文在线| 激情图片小说一区| 免费观看亚洲视频| 成人av地址| 欧美国产日韩xxxxx| 欧美亚洲精品在线观看| 日韩欧美亚洲综合| 中国女人特级毛片| 久久国产精品无码网站| 美女黄色片网站| jizz性欧美23| 欧美在线欧美在线| 午夜免费福利在线观看| 在线播放视频一区| 国产性一乱一性一伧一色| 成人精品小蝌蚪| 国产精品免费入口| 不卡在线一区二区| 91亚洲精品一区二区| 久草免费在线色站| 亚洲欧美日韩精品久久亚洲区| 久久精品久久久久久久| 国产精品日日摸夜夜摸av| 老女人性生活视频| 日韩午夜激情| 色一情一乱一伦一区二区三区丨| 香蕉成人在线| 久久久久久高潮国产精品视| 嫩草在线播放| 91精品久久久久久久91蜜桃| 国产精品50页| 中文字幕av一区二区三区免费看| 亚洲欧美激情一区二区三区| 国产亚洲毛片| 日韩视频在线免费播放| 老司机精品视频在线播放| 国产精品老女人视频| av观看在线| 亚洲天堂av网| 亚洲成人一二三区| 91国产成人在线| 免费人成视频在线| 久久精品一区八戒影视| 亚洲av无码久久精品色欲| 久久福利影视| 日本国产中文字幕| 日韩精品一卡| 九色一区二区| 久久久久亚洲精品中文字幕| 日本久久久久久| 免费在线看污片| 少妇av一区二区三区| 日韩一级片免费在线观看| 欧美亚男人的天堂| 午夜影院在线看| 亚洲啪啪综合av一区二区三区| 超碰97人人干| 成人午夜看片网址| 一区二区久久精品| 水蜜桃久久夜色精品一区的特点| 久久综合久久久久| 我不卡伦不卡影院| 日本亚洲导航| 天海翼精品一区二区三区| av成人综合网| 91精品福利观看| 国产精品电影久久久久电影网| 国产后进白嫩翘臀在线观看视频| 久久精品亚洲国产| 成年人视频免费在线观看| 精品无人国产偷自产在线| www.色视频| 欧美一区二区三区白人| 在线观看免费观看在线| 色8久久精品久久久久久蜜| 1级黄色大片儿| 亚洲成人第一页| 免费一级片视频| 亚洲欧美日本在线| 最新av电影网站| 国产精品国产自产拍高清av| 日本少妇xxxxx| 久久久久久**毛片大全| 亚洲AV无码国产精品| aaa欧美日韩| 国产精品成人无码专区| 高清不卡一二三区| 人妻 丝袜美腿 中文字幕| 国产高清不卡一区二区| 秋霞午夜鲁丝一区二区| 国产激情一区二区三区四区| 三级黄色片播放| 国产在线精品免费| 在线观看免费视频污| 国产一区二区在线观看免费| 国产精品999.| 国产成人午夜高潮毛片| 亚洲一区和二区| 成人免费黄色在线| 国产精品无码一区二区三区免费| 91麻豆视频网站| 麻豆精品免费视频| 国产精品色眯眯| 国产色无码精品视频国产| 亚洲色图欧洲色图婷婷| 一区二区视频免费看| 亚洲永久精品大片| 午夜精品三级久久久有码| 疯狂蹂躏欧美一区二区精品| 天堂网视频在线| 欧美日韩亚洲综合在线 欧美亚洲特黄一级| 中文字幕一级片| 91精品国产综合久久国产大片| 国产伦一区二区| 精品国产91九色蝌蚪| 深夜福利在线观看直播| 亚洲欧美在线免费| 色三级在线观看| 欧美激情性做爰免费视频| 性感女国产在线| 国产精品爽爽ⅴa在线观看| 亚洲日本免费电影| 国产精品一区二区三区在线观| 亚洲理论电影片| 自拍偷拍99| 尤物在线精品| 波多结衣在线观看| 国产激情精品久久久第一区二区 | 日韩三级不卡| 精品久久蜜桃| 色欧美自拍视频| 国产乱淫av片杨贵妃| 久久一二三四| 在线视频观看91| 91在线观看视频| 国产黄色录像片| 欧美日韩国产一区中文午夜| 一级黄色片免费| 亚洲国产精品久久91精品| 成人精品一区二区三区免费| 欧美极品少妇全裸体| 成人看片在线观看| 国产精品一区视频网站| 日韩av自拍| 国产 日韩 亚洲 欧美| 老司机一区二区| 男生裸体视频网站| 亚洲色图欧美激情| 中文字幕在线播| 精品久久久久久久人人人人传媒| 福利片在线看| 7m精品福利视频导航| 久久av网站| 午夜欧美性电影| 日韩一级大片| 69久久精品无码一区二区| 国产视频一区在线播放| www.天天色| 欧美一区二区三区的| 97久久精品人人澡人人爽| 中国特级黄色片| 国产三级精品视频| www.99re7.com| 777久久久精品| 精品久久久久一区二区三区 | 欧美日韩大陆在线| 国产av一区二区三区| 一区二区欧美久久| 在线观看爽视频| 懂色一区二区三区av片| 久久中文字幕av一区二区不卡| 欧美性大战久久久久xxx| 福利电影一区二区| 日韩a级片在线观看| 欧美另类z0zxhd电影| 成人影视在线播放| 日本道色综合久久影院| 美日韩黄色大片| 欧洲精品在线播放| 国产精品18久久久久久vr| 国产第一页浮力| 欧美日韩国产高清一区二区三区| 国产在线网站| 国产91在线高潮白浆在线观看| 全球av集中精品导航福利| 日韩精品久久一区二区| 国产精品影视在线| 神马午夜精品91| 欧美绝品在线观看成人午夜影视| 懂色av中文在线| 国产精品青青在线观看爽香蕉| 精品国产一区二区三区| 久久国产色av免费观看| 26uuu国产在线精品一区二区| 日韩人妻无码一区二区三区99| 亚洲成年人影院在线| av电影免费在线看| 国产一区二区三区色淫影院| 伊人天天综合| 朝桐光av一区二区三区| 午夜精品福利一区二区三区av| 人妻与黑人一区二区三区| 97精品久久久中文字幕免费| 日韩有码av| 国产成人精品视频ⅴa片软件竹菊| 国产欧美日韩精品一区| 在线视频播放大全| 久久综合久久美利坚合众国| 视频在线观看免费影院欧美meiju| 久久99久久久久久| 99精品国产一区二区三区不卡| 东京热一区二区三区四区| 国产一区二区三区在线观看视频| 欧美日一区二区三区| 亚洲制服中文| 国产成a人无v码亚洲福利| 久久9999久久免费精品国产| 精品夜色国产国偷在线| 99re66热这里只有精品4| 最新视频 - x88av| 99久久久精品| 国产精品51麻豆cm传媒| 欧美成年人在线观看| 男人的天堂久久| 午夜久久久精品| 一区二区国产视频| 男女污污视频在线观看| 国产一区二区在线免费| 亚洲午夜久久久久久尤物| 久久久久久久久久久国产精品| 欧美日韩中字一区| 青春草在线免费视频| 欧美亚州在线观看| 国产一区二区三区免费看 | 日韩免费高清一区二区| 欧美性感一区二区三区| 欧美性video| 日本一区二区三区在线视频| 韩日av一区二区| 在线观看亚洲欧美| 久久精品视频一| 久久亚洲黄色| 玖玖爱视频在线| 福利二区91精品bt7086|