使用CoffeeScrip優美方式編寫javascript代碼,javascript代碼

來源:互聯網
上載者:User

使用CoffeeScrip優美方式編寫javascript代碼,javascript代碼

JavaScript無疑是在web最偉大的發明之一,幾乎一切網頁動態效果都是基於它豐富的計算能力。而且它的能力在各種新的JavaScript的Engine下也越來越強了,比如Google Chrome用的V8 Engine。

但是由於誕生的太早,有很多文法定義在今天看來有些效率低下了,一些更加先進的文法形式,由於曆史原因,沒辦法加入到現在的JavaScript語言中,可以說一種遺憾。

世界上的很多天才都在為構建更好的JavaScript而努力。已經有了很多嘗試,其中最有前途的,無非就是CoffeeScript和TypeScript了。面對CoffeeScript,我有一見如故的感覺;而TypeScript也激發了我極大的興趣。CoffeeScript和TypeScript一樣,都是編譯為JavaScript的語言,它們都增強了JavaScript的表達能力。這篇文章是講CoffeeScript的,TypeScript將放在下一篇再講。

所謂編譯為JavaScript,是指CoffeeScript和TypeScript沒有實現自己的運行時,它們都是編譯為等價的JavaScript代碼,然後放在JavaScript的解譯器上運行。

CoffeeScript

簡潔性

CoffeeScript給人最大的印象就是其簡潔的表達。下面代碼是我從CoffeeScript中文摘抄下來的:

# 賦值:number  = 42opposite = true# 條件:number = -42 if opposite# 函數:square = (x) -> x * x# 數組:list = [1, 2, 3, 4, 5]# 對象:math = root:  Math.sqrt square: square cube:  (x) -> x * square x# Splats:race = (winner, runners...) -> print winner, runners# 存在性:alert "I knew it!" if elvis?# 數組 推導(comprehensions):cubes = (math.cube num for num in list)

上面的代碼會編譯為等價的JavaScript代碼:

var cubes, list, math, num, number, opposite, race, square, __slice = [].slice;number = 42;opposite = true;if (opposite) { number = -42;}square = function(x) { return x * x;};list = [1, 2, 3, 4, 5];math = { root: Math.sqrt, square: square, cube: function(x) {  return x * square(x); }};race = function() { var runners, winner; winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : []; return print(winner, runners);};if (typeof elvis !== "undefined" && elvis !== null) { alert("I knew it!");}cubes = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = list.length; _i < _len; _i++) {  num = list[_i];  _results.push(math.cube(num)); } return _results;})();run: cubes

CoffeeScript力求簡潔。其簡潔性首先表現在對一些僅用於文法控制的符號進行了去除。這其中包括:

取消分號

取消var聲明

取消大括弧包圍內層代碼,使用縮排取代

函數調用在沒有歧義的情況下可以省略括弧

var聲明涉及到複雜又很雞肋的JavaScript變數範圍機制。這部分內容先放著不講。CoffeeScript通過完全取消var聲明機制而使得問題得到簡化。總之,在CoffeeScript世界裡,變數不用事先聲明,直接用就是了。而且這種用法基本沒有什麼危險。

縮排在CoffeeScript中不僅僅在於美化代碼,其代表了代碼層次的組織,是有特別的含義的。簡單地說就是,不適用大括弧包圍內層代碼,而是內層代碼要縮排。不同的縮排代表了不同的代碼層次。形式和內容是一致的。

縮排的例子:

#if縮排if true 'true'else 'false'#while縮排while true 'true'#函數縮排(n) -> n * n#對象字面量縮排kids = brother:  name: "Max"  age: 11 sister:  name: "Ida"  age: 9 

在不引起歧義的情況下,CoffeeScript的函數調用可以省略括弧。例如console.log(object)可以簡化為console.log object。所謂引起歧義的一個例子就是無參數的情況下,console.log就不知道是取出函數型屬性log還是調用函數log了。

CoffeeScript的函數運算式也做了極致的精簡精簡。一個單行函數的定義可以這樣:

square = (x) -> x * x

而多行函數也是通過縮排來組織的。一個空的函數最為簡潔,是這樣:->。

函數的這種簡潔表達使得傳遞迴調函數非常便利。一個數組的map可能像這樣就足夠了:

list = [1, 2, 3]list.map (e) -> e+1

而等效的JavaScript代碼就不能這麼馬虎:

list = [1, 2, 3];list.map(function(e) { return e + 1; });

增強表達

CoffeeScript提供了JavaScript所沒有的一些強大的表達文法,這也是被稱為文法糖的東西。在我印象中,這種增強性是很多的,我舉出兩個有代表性的例子:

字串插值法

列表解析

其中字串插值法是對現有字串能力的一種擴充和文法上的簡化;而列表解析就要涉及到觀念上的改變了。前者是一種改良,後者則是一種變革。

字串插值法

在CoffeeScript的字串裡,可以用#{…}嵌入一個運算式。例如:

"#{ 22 / 7 } is a decent approximation of π"

等價於:

"" + (22 / 7) + " is a decent approximation of π";

插值在這裡起到佔位的作用,使得動態內容的字串更容易構建。我想人人都能接受這樣的表達。

列表解析

列表解析是CoffeeScript的世界裡的重要一員。它改變了迴圈的思路。CoffeeScript沒有提供像JavaScript那樣的for迴圈結構,而是統統轉化為列表解析。一個常規的JavaScript for迴圈,像下面這樣:

food_list = ['toast', 'cheese', 'wine'];for (i = 0, len = food_list.length; i < len; i++) { food = food_list[i]; eat(food);}

用CoffeeScript實現就是:

food_list = ['toast', 'cheese', 'wine']
eat food for food in food_list #做個小補充,for迴圈的單條語句的寫法

單單是上面的例子不足以顯示列表解析的強大(卻看到它的簡潔了)。在繼續這個話題之前,我覺得我有必要補充一下另一個涉及到CoffeeScript理念的東西了:一切皆是運算式。

在CoffeeScript世界裡,一切語句都是運算式語句,都會返回一個值。函數調用預設會返回最後一條語句的值。if條件結構也會傳回值,其返回的是執行的最後一條語句的值。迴圈結構有些不同,其會將每次迴圈的結果都儲存在一個數組裡,作為此迴圈結構的值。例如下面代碼的list結果就是[5, 4, 3, 2, 1]。

num = 6list = while num -= 1 num

回到列表解析的主題。與while一樣,for結構也是一種迴圈的表達,其結果也是一個數組。回到先前的例子,下面的小代碼的list結果就是['t', 'c', 'w']。

food_list = ['toast', 'cheese', 'wine']list = (food[0] for food in food_list)

我們已經看到for迴圈的each形式

eat food for food in food_list

以及它的map形式

(food[0] for food in food_list)

下面給出它的filter形式

(food for food in food_list when food is 'wine')

列表解析的特色的地方在於它改變了我們組織迴圈的方式和解析數組的模式。這是一種聲明式的編程方法,告訴程式你想要什麼而不去關心構建的過程。

類的支援

類是CoffeeScript對JavaScript的一個很重要的補充。JavaScript的原型功能很強大,寫法上又恨彆扭。正確地設定原型鏈以實現繼承關係也是個很大的挑戰。CoffeeScript從文法上直接支援類的定義,自然且隱藏細節。

class Animal constructor: (@name) -> move: (meters) ->  alert @name + " moved #{meters}m."class Snake extends Animal move: ->  alert "Slithering..."  super 5class Horse extends Animal move: ->  alert "Galloping..."  super 45sam = new Snake "Sammy the Python"tom = new Horse "Tommy the Palomino"sam.move()tom.move()

從實現上來說,CoffeeScript的類與JavaScript的建構函式和原型鏈那一套並無二致。所以,理解原型機制也是理解CoffeeScript類的基礎。

關於JavaScript的糟粕

CoffeeScript的另一個目標是從文法層面上直接消除JavaScript的被人詬病的一些糟粕部分。前面已經說過關於分號的部分。關於var聲明的部分。分號的機制暫且不去例會,總之CoffeeScript不用再去寫分號了。

在JavaScript當中,最為人詬病的糟粕部分有兩處,因為它們使用的情況最多而且容易出錯。

全域變數

相等比較

全域變數

JavaScript的範圍規則很複雜,涉及到var聲明機制和變數提升。在JavaScript裡,構造一個全域變數是很容易的,有三種方式:

在全域的環境裡用var聲明

var name = 'name';

在函數內用省略var的方式定義

function foo() {  name = 'name';}

綁定到window的屬性

window.name = 'name';

其中第1種和第2種方式是最常見的錯誤用法。首先不推薦直接在全域環境中編碼,而是應該用一個匿名函數包裹起來,將程式的範圍限制在這個匿名函數中。第二種用法完完全全就是忘記了var聲明。而我在實際的JavaScript編碼中,忘記var聲明是常有的事(就像經常忘記行末補上分號一樣)。

而在CoffeeScript裡面就完全沒有這種擔心了。首先,編譯後的JavaScript代碼不會暴露在全域環境裡,所有的代碼都是自動包裹在一個匿名函數(function(){ ... })();內。然後,所有的變數都會自動加上var聲明。這就使得不小心汙染全域的情況很難發生,除非使用賦值到window上。

相等比較

我們都知道JavaScript有兩種比較子:==和===。我們也知道==在使用的過程中會很坑,所以平時都寧願多打一個字元而使用===。CoffeeScript的只有一種比較子==,而它會編譯成JavaScript的===,從而很好地避過了這道坑。

是否該使用CoffeeScript

CoffeeScript簡化和增強了JavaScript的表達能力,儘可能地從文法層面上就能避免JavaScript的一些坑。用它寫代碼,會讓人有更清晰舒適的感覺,而且不容易犯錯。CoffeeScript的初衷就是提供更好的JavaScript。

然而,CoffeeScript與JavaScript是不相容的。它既不是JavaScript的子集,也不是超集,而是與JavaScript有著顯然不同思路的一種語言。用CoffeeScript編程就必然要轉換觀念,儘管這種觀念更好更自然,但卻是有些固步自封的人望而卻步的主要原因了。

CoffeeScript並不是適合每一個人的。有些人對於用縮排組織代碼層次完全不能接受,也不能接受用箭頭函數表達法。對於他們來說,去掉function關鍵字和大括弧的組織怎麼看都怎麼地不順眼。

列表解析很強大,卻也顯得過於簡潔了。對於習慣了構造冗雜JavaScript程式的人們來說,並不習慣這種表達方式。

總之,是不可強求別人去學習使用CoffeeScript。JavaScript已經足夠強大,只要足夠小心,完全可以使用JavaScript很好地完成工作。對於那些想要嘗試CoffeeScript,我們也要給予鼓勵的態度,他們是求新求變的勇士。CoffeeScript真的值得一試,而且它真的很小巧,完全掌握它不是件困難的事。

對於在團隊推行CoffeeScript,我本人更是持有保守的看法。如果團隊從一開始就使用CoffeeScript還好。如果是要從CoffeeScript轉為JavaScript,就要謹慎行之。一種可行的方式是先嘗試在一個小項目中使用CoffeeScrip,看看效果如何。

對於個人來說,就沒有什麼限制了。如果真的喜歡,就去嘗試吧。你可以使用CoffeeScript寫指令碼,構建自己的網站,做一些小玩意。

以上內容是小編給大家介紹的使用CoffeeScrip優美方式編寫javascript代碼,希望大家喜歡。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.