聊聊JS語言是如何從前端移到後臺的
出處
js的出處大家都知道,先是netscape給自己瀏覽器寫的,後來標準化了,整合到ECMA標準集中,成為ECMAScript 262標準,後來伴隨html5制定了265版本。
師出同門的還有flex 所用的action script, 和photoshop所用的指令碼,最近還聽說有些硬體也用上了js。所以,大家今後其實還可以到這些領域去施展一下拳腳。
js起什麼作用?
js 首先是一種計算機語言,其最核心的功能是:
- 按邏輯執行程式
- 操控資料
- 輸入/輸出
其次才是它的語法特性(比如OOP)、執行特性(比如非同步)、易用性(比如自動記憶體管理)。
就其核心功能而言,js跟其它任何一門語言都無差別。
js的哪些特性是專為瀏覽器設計的?
js在瀏覽器中的執行,執行環境上下文是由瀏覽器程式賦予的,即window物件。因此,瀏覽器中執行時,this即是指window。
js對瀏覽器的主要用途有二:
- 實現DOM標準。如構造及儲存節點樹、提供訪問和操控方法、響應節點事件(mouseOver, click...)
- 與瀏覽器環境互動。如與視窗物件(Window)、Location、History、Navigator、Screen互動
上面第1點中的事件
問題一定要注意。我也是直到今天才知道這是DOM標準的一部分,而javascript當初為了實現這個標準,將響應事件的的能力內化在了語言中。也就成了後來大家所津津樂道的一大特性。其實,任何一種需要操控UI的語言都需要具備這種能力,或者通過別的方法變相實現這種能力(比如執行緒)。而那些不需要處理UI的語言就沒怎麼考慮過這個問題,如php,
ruby, python, java,這些語言對事件的響應幾乎都是通過執行緒實現。但javascript是單執行緒的,無法啟動新執行緒,因此事件就成了變相多執行緒方式。
移植到瀏覽器以外的環境執行需要具備什麼條件?
我以前不知道瀏覽器有webkit和V8的時候,以為瀏覽器是一個整體性的,不可分割的軟體。知道後,才發現原來瀏覽器內UI元素的管理和程式執行環境是分別由不同的引擎在支撐。
既然程式由專門的引擎(虛擬機器)在支撐,那這個虛擬機器就可以移出來。但是,脫離了瀏覽器的環境,移出來做什麼呢?
當然是做些常規程式做的事情:像perl一樣做系統管理指令碼
,或是像php/java那樣做伺服器
,或者像C一樣無所不能
。
- 但既然移出來到作業系統所提供的環境執行,那程式本身的儲存方式很大可能性就是檔案,因此,操作檔案的功能也必不可少。既然可以操作程式原始檔或執行檔案,那普通檔案也自然不在話下,很多檔案可以用來做為資料來源或儲存結果。
- 進一步考慮檔案操作。檔案如何讀入?讀入後如何儲存?無論是原始碼這樣的ASCII字元還是圖片、視訊、word文件這種非ASCII資料,要讀進來,就需要具備Read()方法,存起來就需要Write()方法。而檔案讀寫肯定不能一個位元組一個位元組的操作,所以,還需要有二進位制資料的容器,Buffer就是幹這個的。考慮到不同的CPU和作業系統,以及網路傳輸規範等情況,還需要對大端序和小端序的支援。
- 要做伺服器,那就必須能夠開啟一個網路埠進行監聽。因此,網路操作能力也需要具備,其實這也就是擴充套件一個跟作業系統間的介面而已。這在瀏覽器上也是可以的,但是沒必要。
- 進一步考慮網路操作,網路不能向磁碟一樣預先知道其確切的傳輸量。而是一個數據流,因此,需要一個流式的讀寫方法。
- js雖然是可響應事件的,但事件是為DOM設計的,比如繫結物件必須是DOM節點(非HTML),事件會向父節點傳遞(冒泡)。對於更為常規的程式設計,需要不一樣的事件機制,以及脫離DOM規範的設計。因此,需要實現一個額外的事件管理器。這就是NodeJs中的Event Class。
- 有時需要呼叫那些成熟軟體,就需要跟安裝在作業系統上的其它程式互動,通過在作業系統提供的shell環境,發起shell指令呼叫其它程式。這就是NodeJs中OS模組的作用。
總結一下,需要移出來到作業系統的大環境中執行,需要以下特性:
- 檔案操作
- 流式讀寫
- 二進位制資料容器
- 網路操作
- Event Class
- shell互動
如何操控DOM以外的物件?
- 網路:
- 資料庫:
- photoshop圖層:
- 檔案:
- 二進位制資料:
- 聲音:
- 串列埠:
- USB裝置:
總結:
無論哪種,它們都只是一個IO物件,這些物件都是二進位制資料,或者是二進位制資料驅動的。所以只要你能控制這些二進位制資料,並能讀取或寫入到對應的地址或裝置裡去,那就可以操控它。對js而言,涉及兩個問題:
- 二進位制資料的操縱需要語言本身支援(其實幾乎所有語言都支援二進位制資料的,但js本身恰恰並未支援,所以NodeJs一上來就先解決了這個問題);
- 地址和裝置的讀寫控制由作業系統管理,所以要額外新增一些介面來跟作業系統溝通。這也是NodeJs需要一個標準庫的原因。
補充問題
- 標準庫沒涉及到的物件怎麼辦?比如遙控飛機、控制門鎖、藍芽通訊、各類感測器資料獲取等。這些裝置的控制在標準庫中沒有,但屬於作業系統可控的範圍,因此,只要補充對應的操作庫即可。這就是NodeJs留有C++介面的原因。
- 那些作業系統管不了的事情怎麼辦?比如photoshop圖層、畫筆、flex中的元素、動畫等等。這些屬於應用層之上的物件,就需要應用自己建立一個執行環境,並賦予執行上下文,定義各類物件和執行邏輯。這樣就可以了。
跟其他語言有什麼異同?
從最底層的執行邏輯上講,js跟其它語言沒有什麼差異,都是以邏輯結構做為執行條件。
從執行環境層面來說,各種語言的執行順序略有不同,有的語言是以順序執行,有的靠觸發,但根本上都是順序執行的,只是執行的範圍有所不同。因此,其執行是嚴格可預測的,而不能預測的只是事件發生的時間。
對JS應用的展望
js可以在瀏覽器上執行,也可以在伺服器上執行,這是大家已經看到的。但其實它做為一種常規語言,可以做幾乎任何事:
- 做系統管理指令碼。
- 做普通GUI程式的控制語言。這需要擴充套件繪圖模組,並在應用程式中整合js引擎。實際上現在linux上有個專案(Seed)就已經實現了,其圖形庫是GTK,控制語言使用javascript。
- 做Android, ios平臺上的普通app。實際上現在的phoneGap(Cordova)就是將webkit+js引擎預先整合到app中,開發者僅需像開發web一樣開發即可。但這種app需要每個都整合一個webkit+v8(或其它js引擎)。更好的方式是整個大環境就是一個webkit+v8,然後每個app就只有相應的html, css, js程式碼即可,firefoxOS既是如此。要做手機app,則需要js引擎補充實現各種裝置訪問介面。如撥號、3D感測器、攝像頭、GPS、藍芽等。
- 在帶作業系統的微型PC上執行。比如前面帖子中有人編譯到了openWRT上;還有一個控制auduino的NodeJs模組(名叫Johnny-Five)
- 其它IO密集,但處理時效性要求高的領域裡
- 但也有例外,js也有不能做的事情:
- 微控制器程式,或者實現一個裸機作業系統。因為js必須要一個虛擬機器來執行,而虛擬機器本身還不具備作業系統的功能。如裝置管理、記憶體管理(這裡可不是指自動垃圾回收機制,而是真正的實體記憶體)、任務排程(當然,單一功能的裝置上,單執行緒的js無需理會這個需求)。
- 科學計算。(這個不知道我說的對不對,求指正)