JavaScript の控えめな弟として、Coffeescript は非常に優れており、これを使用すると開発効率が向上し、コードエラーが減り、開発の楽しみが大幅に高まります。できる限り自分のプロジェクトにコーヒーを使用すべきだとますます感じています。
しかし、あなたも私と同じかもしれません。coffeescript の構文を理解し、試してみる準備をした後、それをプロジェクトに導入する方法について心配しています。
上司のようにコードに命令する
CoffeeScript は、クールな配列反復メソッドを多数提供します。最も優れた点は、これが配列だけでなく jQuery オブジェクトでも機能することです。詩的なコードを書いてみましょう:
formValues = (elem.value for elem in $('.input'))
このコード行は次の JavaScript に変換されます:
var elem, formValues; formValues = (function() { var _i, _len, _ref, _results; _ref = $('.input'); _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { elem = _ref[_i]; _results.push(elem.value); } return _results; })();
正直に言うと、このようなコードを書くのは最初は本当に怖いですが、CoffeeScript の魔法を受け入れ始めると、虜になるでしょう。
通常の方法を使用したバインド
jQuery のコールバックで「=」を使用すると、オブジェクトにメソッドを手動でバインドする手間が大幅に軽減されます。いくつかのコードを見てみましょう:
object = func: -> $('#div').click => @element.css color: 'red'
以下はコンパイルされた Javascript 出力です:
var object; var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; object = { func: function() { return $('#div').click(__bind(function() { return this.element.css({ color: 'red' }); }, this)); } };
コード内の @要素は、object.element = $('#some_div') など、他の場所で指定された jQuery オブジェクトを指します。
「=>」を使用して指定されたコールバック関数は、元のオブジェクトに自動的にバインドされます。これは素晴らしいことです。
これは 2011 年に関数が呼び出された方法です
これを見てください:
$.post( "/posts/update_title" new_title: input.val() id: something -> alert('done') 'json' )
CoffeeScript を使用すると、複数のパラメータを複数行に記述して呼び出すことができます。カンマと中括弧はオプションです。これにより、$.post() や $.animate() などの jQuery の長いシグネチャを持つ一部のメソッドが読みやすくなります。別の例を次に示します:
$('#thing').animate width: '+20px' opacity: '0.5' 2000 'easeOutQuad'
おいしいコーヒーですね? 最初のパラメーターは匿名オブジェクトであることに注意してください。関数呼び出しではメタ括弧を省略することもできます。
初期化をよりセクシーにします
初めて jQuery を使い始めたとき、ページを次のように初期化しました:
$(document).ready(function() { some(); init(); calls(); })
CoffeeScript と jQuery の新しいバージョンにより、上記のコードは非常に魅力的に進化しています。
$-> some() init() calls()
CoffeeScript の関数定義構文はすでに非常に優れていますが、このような状況で使用できることにより、さらに優れたものになります。 CoffeeScript では、コールバックを必要とするすべての関数呼び出しが非常に簡単であることがわかります。
実際、coffeescript は JavaScript に 1 対 1 で変換できるため、非常に柔軟に使用できる言語です。 プロジェクトに導入する方法も複数あります。ここではまず、nodeプロジェクトにcoffeescriptを導入する方法をまとめ、それぞれの方法のメリット・デメリットを比較していきます。
coffee コマンドを直接使用して純粋な Coffeescript プロジェクトを実行します
一般に、coffeescript について言及すると、js の影から決して逃れることのできない javascript の弟であると自然に考えるでしょう。実際、これを独立した言語と考えることができます。 ノード プラットフォームにコーヒー スクリプト パッケージをグローバルにインストールすると、コーヒー コマンドを通じてコーヒー スクリプト インタラクティブ インターフェイスに入ることができることは誰もが知っています。これを repl と呼ぶこともできます。プロジェクトが完全にコーヒーで書かれている場合は、エントリ スクリプトで直接コーヒー コマンドを使用するだけです。たとえば、エントリ スクリプトの名前が「app.coffee」の場合、次のように実行します。
coffee app.coffee
注意,这里的扩展名coffee是不能省略的。
这个方式应该说是使用coffeescript最“官方”的方式。简单,直接!而且,一旦你以一个coffee文件作为项目的入口, 那整个项目就同时兼容coffee和js了。你在项目里可以任意require js或coffee文件及模块, 甚至可以在项目中的js文件中随便require coffee文件。并且在你引用无论是coffee还是js文件的时候都无需扩展名, 只要前面部分名称不冲突就行。
这个方式有个最大的问题就是,如果它作为一个模块,只能被用于coffee项目;如果他作为一个应用, 运行环境必须安装coffee-script。毕竟coffeescript现在还是一个小众语言,它作为模块时丧失了js用户实在可惜。
另一个也许存在的缺点是性能方面的,毕竟node里面只有js引擎,coffee代码需要先编译为js再运行, 这个过程是要消耗一点点时间的,尽管coffee到js的编译速度其实挺快的。不过这应该不是什么大问题, 一般来说,require都是写在文件的顶部,也就是应用在启动的时候就一气儿把该require的文件都require了, require的时候coffee就被编译成了js放到了js引擎中,那么编译消耗的那点时间都集中在了应用启动时, 运行时几乎不会遇到require新的coffee的情况了。node最常见的使用场景是web服务器,这就更没问题了。
在javascript项目中引用coffeescript
npm中的coffee-script既可以全局安装,也可以作为项目的一个模块安装。那coffee-script作为项目的一个模块有啥意义呢? 其实是给项目添加了一个coffeescript的编译器,这个项目就可以在运行时随时编译coffee文件。
你一定希望像第一种方式里那样随便引用coffee文件。没问题,只需要注册一下。假如你的项目入口文件是app.js, 那么只需要在这个文件最前面加上这么一句:
require('coffee-script/register');
然后你就可以在项目中随便require coffee文件了。
这个方式本质上和第一种方式没啥区别,只不过coffee-script没安装在全局,因此你的模块可以独立存在, 作为应用也不需要环境安装好coffee-script了。
缺点嘛,我觉得最大的问题就是容易让代码有些乱,一会儿js,一会儿coffee,当然第一种方式也可能会这样, 不过都用coffee启动了里面应该不会写js了吧……总之我觉得一个项目还是把语言统一起来比较好 (遗憾的是我主要用这种方式,在一个已经用js写出了大体结构的项目里,我就想用coffee肿么办……)
性能问题上跟第一种方式一样,不多说了。
正统的方式——编译
一说编译,就感觉回到了正儿八经的C或Java的时代。的确,作为一个编译型语言,编译后再运行才是正道。 c有gcc,java有javac,cofee有coffee -c。
要编译一个cofee文件很简单,比如要编辑app.coffee这个文件,就在文件的当前目录执行:
coffee -c app.coffee
一个名为app.js的文件就出现在当前目录下了。这个指令也可以应用于目录, 比如你把项目中所有的coffee源文件放到了src目录下,那就执行:
coffee -c src
src目录及其各级子目录下的所有coffee源文件都会编译成js文件,放到和源文件相同的目录中。
不过对于大型项目,把源文件和编译结果文件放到一起可不太好。指定一个输出目录就行了:
coffee -c -o outputs src
这个指令的参数顺序有点奇怪。在coffee的帮助里是这么定义的:
coffee [options] path/to/script.coffee -- [args]
注意,所有的选项(options)都在coffee和文件路径之间。而最后的args是把目标文件作为脚本执行时给传递的参数。 也就是说所有的选项都放在coffee和文件名之间就可以了。 而-c这个选项是单独的,没有自己的参数,它只表示要把指令最后面提供的那个文件给编译了,所以写成这样也行:
coffee -o outputs -c src
假如想再加个选项,让编译结果不被自执行函数体包围,就是:
coffee -o outputs -c -b src
再假如想把所有源文件编译成一个名为out.js的目标文件,就是:
coffee -o outputs -c -j out src
如果每次改点代码都要这么执行指令也挺烦人的。coffee指令有一个选项-w可以监视源文件的变动而自动编译:
coffee -o outputs -c -w src
大規模なプロジェクトの場合は、すべての開発者が 1 つの命令だけですべてのコンパイル作業を完了できるように、事前にコンパイル方法を決定することが最善です。これには自動構築が必要です。
offee は、C の世界における make に似た自動ビルド ツール、cake を提供しています。 ただし、公式 Web サイトに記載されているように、cake は非常にシンプルなビルド システムです。実際、cake の機能は、cakefile という名前のスクリプトを実行することであり、cakefile スクリプトは Coffeescript で書かれています。このスクリプトは、命令とそれに対応する記述および実行関数を宣言するために使用される、タスクなどの非常に限定された組み込み関数のみを提供します。もう 1 つは、純粋なノード プロジェクトを作成することです。コンパイルを完了するには、node の fs モジュールを使用して、coffee モジュールによってコンパイルされた文字列を出力するか、child_process モジュールを使用してシェル命令を実行する必要があります。実際、ケーキ構築のターゲットは必ずしもコーヒーである必要はありません。ケーキは実際にノード スクリプトを実行し、あらゆる自動化されたものを処理できるからです。
さらに、有名な Grunt や国産の fekit など、コーヒーの自動コンパイルを完了できる、より優れたサードパーティの自動構築ツールもいくつかあります。
このオーソドックスなコンパイル方法は最も信頼性が高く、経験豊富なプログラマに好まれるはずです。これにより、チームは固定された開発モデルを形成できます。 さらに、コンパイルされたプロジェクトは純粋な js プロジェクトになり、アプリケーションとして直接実行する場合でも、他のプロジェクトによってモジュールとして参照される場合でも、追加の依存関係は必要ありません。 また、実行時にコンパイルする必要がないため、コンパイルによるパフォーマンスの問題が発生しません。
欠点は、面倒なことです。小規模なプロジェクトを実行している場合、cakefile を作成したり grunt を設定したりするだけで半日かかりますが、それだけの価値はありません。
jQuery、node.js、JavaScript での Coffeescript の導入を通じて、Coffeescript について新たに理解できましたか?