書籍転載:JavaScriptライブラリ実践活用[厳選111]
オブジェクト指向でコードを記述する[CoffeeScript]
書籍転載の14本目(書籍内の番号は「63」)。CoffeeScriptを使用すると、クラスベースのオブジェクト指向で記述できる。その内容を説明する。
書籍転載について
ご注意
本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどはBuild Insiderのそれとは一致しません。あらかじめご了承ください。
JavaScriptは、初心者でも始めやすい言語ですが、深く理解しバグの少ないコードを書くには言語仕様上の「罠」が潜んでいます。その一例にオブジェクト指向への対応があります。JavaScriptはプロトタイプベースのオブジェクト指向であり、クラスベースのオブジェクト指向ではありません。そこでCoffeeScriptを使用すると、クラスベースのオブジェクト指向で記述できます。
- 名称: CoffeeScript
- 分類: 小ネタ
- URL: http://coffeescript.org
- 関連ファイル: coffee-script.js
ここでは、関数とオブジェクト指向について説明します。
関数
関数は、JavaScriptよりも幅広い表現力を持っています(リスト063-01)。
# 1関数の宣言
square = (x) -> x * x
# 引数が存在する関数
sum = (n, m) -> n + m
# 2引数にデフォルト値がある
minus = (n = 2, m = 4) -> n - m
# 3複数行の関数
multi = (n) ->
if n < 2
square(n, 5)
else
sum(n, 2)
# 4可変長の引数
sum = (nums...) ->
result = 0
result += num for num in nums ―――5
result
|
1関数は「->」で定義します。1行にも複数行にも記述することができます。また、returnを省略することができ、自動的に最後の構文に自動的にreturnが付きます。
2引数にデフォルト値を指定できます。コンパイル後のコード(リスト063-02)を見ると、if文でnullだった場合にデフォルト値を格納します。変換後のコードを見ると、その意図がわかりやすいと思います。
3複数行での関数も定義できます。この場合も最後の処理は自動的にreturnが付きます。
4可変長の引数を...で定義できます。
5配列を回して格納していくことも可能です(for~in命令については後述)。コンパイル後のJavaScriptを見てみると、__slice.call(arguments, 0)で明示的に配列に引数を入れています。JavaScriptで記述すると、ここまで複雑な構文になりますが、CoffeeScriptで記述すると少ない行数で記述できるようになります。
(function() {
var minus, multi, square, sum,
__slice = [].slice;
square = function(x) { ――――――1
return x * x;
};
sum = function(n, m) {
return n + m;
};
minus = function(n, m) { ―――――2
if (n == null) {
n = 2;
}
if (m == null) {
m = 4;
}
return n - m;
};
multi = function(n) { ――――――3
if (n < 2) {
return square(n, 5);
} else {
return sum(n, 2);
}
};
sum = function() { ――――――4
var num, nums, result, _i, _len;
nums = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
result = 0;
for (_i = 0, _len = nums.length; _i < _len; _i++) {
num = nums[_i];
result += num;
}
return result;
};
}).call(this);
|
クラス型オブジェクト指向
JavaScriptはクラス型オブジェクト指向ではなく、プロトタイプベースのオブジェクト指向となっており、処理の考え方が違います。Javaなどの他の言語と同様のオブジェクト指向の感覚で使用すると、想定どおりに動作しないことがあります。
そこで、CoffeeScriptでは、クラス型オブジェクト指向をサポートしています。これだけでも、CoffeeScriptを利用する価値があるでしょう。
ではリスト063-03を例に、CoffeeScriptでのクラス型オブジェクト指向の書き方をを見ていきましょう。
###
クラス型オブジェクト指向
### # 1クラス宣言
class Member
# 変数の宣言
yasunishi: 'Hello' # publicなインスタンス変数
@yamada: 'Hello' # publicなstatic変数
takano = 'Hello' # privateなstatic変数
# 2コンストラクタ(@を付けることで引数をインスタンス変数に格納)
constructor: (@yasunishi) ->
# 3メンバ関数
func: ->
@yasunishi # publicなインスタンス変数へアクセス
Member.yamada # publicなstatic変数へアクセス
takano # privateなstatic変数へアクセス
# 4staticなメンバ関数
@staticfunc: ->
# staticな関数からstaticなプロパティへは@でアクセスできる
@yamada
# 5継承
class SubClass extends Member
func: ->
# スーパークラスの同名のメソッドを呼び出す
super()
|
1クラス宣言
class命令で行います。変数の宣言は宣言の方法によって扱いが違います。
- 変数名:内容(publicなインスタンス変数)
- @変数名:内容(publicなstatic変数)
- 変数名=内容(privateなstatic変数)
2コンストラクタ
引数に@とインスタンス変数名が付いていますが、これは次のようなインスタンス変数に引数を格納するコードの省略形です。
constructor: (arg) ->
@yasunishi = arg
|
3関数宣言
メンバ変数へのアクセス方法です。@は、メンバ関数内だとthisと同じ意味となり、このサンプルの場合、this.yasunishiとなります。publicなstatic変数はクラス名.変数名となり、privateなstatic変数は変数名のみでアクセスします。
4staticな関数
@を付けることにより、staticな関数になります。staticな関数からstaticなプロパティへは@でアクセスできます。
5継承
extends命令でスーパークラスを指定します。また、関数内ではsuperメソッドで同名のスーパークラスのメソッドを呼び出します。
コンパイルを行うとリスト063-04のように変換されます。
(function() {
var Member, SubClass,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; }ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
Member = (function() {
var takano;
Member.prototype.yasunishi = 'Hello';
Member.yamada = 'Hello';
takano = 'Hello';
function Member(yasunishi) {
this.yasunishi = yasunishi;
}
Member.prototype.func = function() {
this.yasunishi;
Member.yamada;
return takano;
};
Member.staticfunc = function() {
return this.yamada;
};
return Member;
})();
SubClass = (function(_super) {
__extends(SubClass, _super);
function SubClass() {
return SubClass.__super__.constructor.apply(this, arguments);
}
SubClass.prototype.func = function() {
return SubClass.__super__.func.call(this);
};
return SubClass;
})(Member);
}).call(this);
|
※以下では、本稿の前後を合わせて5回分(第12回~第16回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
12. JasmineのSpy機能でテストダブルを作成する
書籍転載の12本目(書籍内の番号は「109」)。Jasmineでテスト対象オブジェクトが持つメソッドの戻り値を固定値に変更したり、そのメソッドが実行されたかどうかを検証したりするために、Spy機能を使用する方法を解説。
13. 短くかつ安全で高性能なコードを書く[CoffeeScript]
書籍転載の13本目(書籍内の番号は「62」)。短い記述で、安全かつ高性能なJavaScriptコードを生成できる「CoffeeScript」の基本的な使い方を説明する。
14. 【現在、表示中】≫ オブジェクト指向でコードを記述する[CoffeeScript]
書籍転載の14本目(書籍内の番号は「63」)。CoffeeScriptを使用すると、クラスベースのオブジェクト指向で記述できる。その内容を説明する。
15. 処理を短く記述する[CoffeeScript]
書籍転載の15本目(書籍内の番号は「64」)。CoffeeScriptの基本構文のうち、数値や文字列表現、配列、for~in、unless/untilの記述方法を説明する。
16. JavaScriptでクッキーを簡単に操作する[jquery.cookie]
書籍転載の16本目(書籍内の番号は「61」)。JavaScriptでのクッキー操作をごくシンプルなコードで実装できる「jquery.cookieプラグイン」の基本的な使い方を説明する。