咱們沒法在一篇博文裏解釋JavaScript的全部細節。若是你正或多或少地涉及了web應用程序開發,那麼,咱們的Java工具和技術範圍報告揭示了,大多數(71%)Java開發者被歸到了這一類,只是你對JavaScript遇到了阻礙。javascript
毫無疑問,你已經知道了Java和JavaScript,無論它們有着多麼相似的命名,彼此沒有共享太多共通之處。Java的靜態類型、符合直接規律的簡單語法和冗長,與JavaScript的動態、缺少一致性原則和怪異,有着巨大的不一樣。html
然而,JavaScript是web的編程語言,最近因爲Node.js和JVM本身的Nashorn JavaScript引擎的發展,在服務器端得到了至關的注意。前端
本文,我不想只是漫談JavaScript的好與很差,或重複任何人都能免費找到的、不可勝數的JavaScript教程。我想列出一些有助於理解JavaScript作爲一種語言的技術點,並從接近horse的角度來理解。java
咱們將在本文包含下列語言級別的技術點:git
另外,你會找到一些工具方面的推薦,沒有這些工具,你是不想着手JavaScript項目的,包含了構建系統的代碼質量分析和測試框架方面的工具。github
毋庸置疑JavaScript是web編程語言,是不少其它語言的編譯目標,也是用來證實有時候人們只是想擁有更多自由時間的終極方式。儘管如此,這不是一件壞事。每一臺可以瀏覽現代網站的電腦都裝備了具備性能和可用的JavaScript引擎。最重要的是,JavaScript代碼能夠在後端運行。web
內置到咱們喜好的JVM的、輕量級高性能JavaScript運行時Nashorn,徹底可以解釋JavaScript腳本,還可以解釋項目中帶有Java代碼的JavaScript腳本。編程
鑑於每臺電腦運行時均可得到的自由,JavaScript成爲Java體驗的完美延續。gulp
JavaScript中的函數是第一類公民,它們是值,可被存儲在變量裏、傳遞給其它函數、在適當的時候再執行。後端
這打開了函數式編程世界的大門,這是結構化JavaScript編程的完美方式。
注意,JavaScript裏的對象是任何東西的映射,對象的每一個特性(attribute)都在同一個映射裏:函數、屬性(property)、構造器;易變性帶來了更大的隱患,而對於Java,你至少可以確保方法和字段結構在某種程度上是穩定的。
反過來,這使得函數式編程更加有利:涉及到小的、可理解函數和不變的數據結構是在JavaScript裏運行的方式。
這不是沒有依據的,下面是在JavaScript裏定義一個reduce函數的例子,來自於《Eloquent JavaScript》一書。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
function
forEach(array, action) {
for
(
var
i = 0; i < array.length; i++) {
action(array[i]);
//apply action to every element of the arra.
}
}
function
reduce(combine, base, array) {
forEach(array,
function
(element) {
base = combine(base, element);
// and here we apply function passed as ‘combine’ parameter to ‘base’ and ‘element’
});
return
base;
}
function
add(a, b) {
// btw, this is how you define a function in JavaScript
return
a + b;
}
function
sum(numbers) {
return
reduce(add, 0, numbers);
}
|
注意:咱們沒有在這裏使用reduce的遞歸版本。JavaScript沒有以尾調用【注1】爲特點,這意味着每一個函數的遞歸版本都將用到棧的深度,和Java同樣,若是你遞歸太深,程序就崩潰。
JavaScript的繼承是基於原型的。即,你沒有擴展了其它類型的類型,而實際上,你擁有的實例從其它實例繼承了功能。
想象一下,對象A就像一個映射,咱們剛纔稍微提到了一些、可是用了不一樣的視角,而後另外一個相似映射的對象B從A繼承了一切。
這說明B能夠訪問A全部部分:A的方法、字段等等。
在實踐中,我歷來沒有看到有人實際使用簡單的基於原型的繼承。一般當某人須要繼承時,他只是構造類,所以你能夠用到全部普遍的技能,和基於類的繼承的工做模式。
——Rene Saarsoo,XRebel前端工程師
我不太肯定Java開發者應該從中吸收什麼,可是要小心繼承方式的不一樣,對於父級對象要格外留意、而不要意外地改變整個程序的行爲。
列出不可靠的JavaScript設計上的決定比想象中要容易。在JavaScript程序中要避免的最明顯的地方就是全局變量的聲明。
注意,在JavaScript裏,不管何時,不使用var關鍵詞定義變量,那麼定義的變量被推到了它們被定義的做用域頂端。這意味着,每一個用這種方式定義的變量將跑到全局範圍頂部,這會引起衝突以及你和同事不可預期的頭痛。
能夠開啓strict模式。只需在腳本文件頂部寫上「use strict」,那麼不經意編寫的全局變量聲明將顯示錯誤。
JavaScript與Java另外一個重要的不一樣點在於,前者是動態類型語言,其真諦是全部東西均可以是任何類型。這很明顯了,實在不能再強調了:不要針對不一樣類型的值,去複用相同的變量。
跟蹤剛開始是個string類型的變量,可是如今它成了浮點數、或者函數了,相信我!
還有,我不想太深刻類型和布爾值的討論,可是要警戒JavaScript引擎扔給你的隱式類型轉換。
正如我上面提到的,在編程上要更加註意這種語言的語法和怪癖,而不只僅是知道。項目不多因爲語言的不足而失敗,更多的失敗是與整體項目框架不足有關。下面是有助於你交付項目的一些工具。
大部分項目是不一樣的,其複雜度和需求致使了大量的細節,你該如何着手代碼庫呢。儘管如此,在全部地方都有一致性的目標,那就是代碼質量。
是的,代碼質量,對於任何開發者來講,最重要的工做就是交付。可是不要在質量上妥協,不要對你提交的代碼感到不自信就不情願與同事分享。
幸運的是,JavaScript有一套得體的解決方案——JSHint。JSHint是爲JavaScript量身打造的靜態分析工具,與應用於Java代碼的FindBug相似。JSHint能夠在你的代碼庫運行,並高亮出可疑的或有問題的地方,即便你不會立刻產生bug,但這些地方未來變得難以維護。在項目中支持它至關簡單。幫本身一個忙——若是你在寫JavaScript代碼,就用JSHint讓它更安全、少一些尷尬。
REPL表明「讀取-求值-輸出」循環(Read-Eval-Print Loop)【注2】,是不少動態語言的強大工具。若是你看過Scala或Groovy,你必定可以理解這個概念。
激活JavaScript REPL的一種途徑是打開瀏覽器的控制檯,它產生了對JavaScript代碼求值的界面。
另外一個比較方便的工具是jjs,它捆綁在JDK1.8。
它是命令行工具,容許你訪問JDK中的Nashorn JavaScript 引擎,徹底有能力執行那些甚至最爲嚴格的JavaScript腳本。
對於任何一個項目,你都想運行一些測試。測試對於動態類型的語言尤其重要,最好選擇一種測試框架。我推薦Jasmine,它是用於測試JavaScript的行爲驅動開發框架。
在Jasmine,你用describe描述測試套件,它阻止了你想測試的代碼訪問。在測試中的代碼完成後,你expect一些結果。
很明顯這裏不是要給出教程,可是我想讓你一瞥JavaScript代碼看起來是多麼地優雅。Jasmine是JavaScript項目最好的實踐之一,咱們私下在產品開發中應用到了ZeroTurnaround項目,尤爲是對於富含JavaScript的不間斷運行的交互分析器XRebel。
最後,你的項目將須要的、比較重要的是構建工具。若是你在Java項目中使用JavaScript,請確保你能夠避開Java構建工具,這就差很少足夠了。可是,對於獨立的JavaScript項目,沒有必要引入龐然大物—Maven【注3】。
能夠考慮的JavaScript項目用到的構建工具是GulpJS【注4】。它是基於插件的構建系統,你能夠爲其指定任務。任務能夠是「拷貝src目錄下的.js文件到dest」、或「壓縮個人JavaScript代碼用於生產環境」。讓人受到震動的是,GulpJS把任務相關的文件流加入過濾器,所以你能夠把上面的兩個任務加入一次有效的清掃中。
還有大量的可用插件,藉助適當的構建系統,你將發現項目中的協做會輕鬆不少。
咱們只是看到了JavaScript的冰山一角,並儘可能介紹一些Java開發者在解決JavaScript時應該知道的概念和工具。天然地,這裏沒有提供要學習的完整的技術清單,可是若是你正準備義無反顧地深刻JavaScript項目,這會幫助你起步,擁抱JavaScript的怪癖將有助於你不會頻繁地沮喪。
你瞭解讓JS開發者走向快樂的祕密或最佳實踐嗎?毫無疑問應該去分享!在下面評論或在Twitter:@shelajev上與我交談。我樂於聽到你的想法!
原文:javascript-explain-it-like-im-a-java-developer 翻譯:labazhou