Cookbookがあった。
CoffeeScript Cookbook
Cookbookとは「諸々の問題を華麗に解決しよう!」というレシピ本みたいなの。CoffeeScriptの特徴というより、単なるプログラムの書き方の寄せ集めみたいなノリでもある。
なので、CoffeeScriptの特徴を捉えてるやつをピックアップして見てみよう!
スルーしてるやつ
- 公式ドキュメントに載ってる基本的なものはだいたいスルー
- あと変態ぽいやつ(例えば「Repeating a String」)もスルー。(直感的でない)
- 単純なjsのtipsもスルー (Recursive Functions)
スタティックなメソッドを使おう
なぜか公式に書いてない、staticなやりかた。
classのメソッド、プロパティに@をつけるとOK。
class Songs
@_titles: 0 # Although it's directly accessible, the leading _ defines it by convention as private property.
@get_count: ->
@_titles
constructor: (@artist, @title) ->
Songs._titles++
ディープコピー
ガチでディープコピーするとき。
clone = (obj) ->
if not obj? or typeof obj isnt 'object'
return obj
if obj instanceof Date
return new Date(obj.getTime())
if obj instanceof RegExp
flags = ''
flags += 'g' if obj.global?
flags += 'i' if obj.ignoreCase?
flags += 'm' if obj.multiline?
flags += 'y' if obj.sticky?
return new RegExp(obj.source, flags)
newInstance = new obj.constructor()
for key of obj
newInstance[key] = clone obj[key]
return newInstance
ちなみにJSONのクローンは
JSON.parse(JSON.stringify(object))
で強引にクローンできる。
ES5を使った配列のmap, every, select
とあるが、ES5。IE8を含めるならunderscore.jsなどで吸収しないといけない。(EcmaScriptの各ブラウザ対応状況)
ちなみにCoffeeScriptだと、配列処理はわりと楽に書ける。ので、ES5使わなくていいかもね。
↓Mapの代用。
list = [1, 2, 3]
double = (value *= 2 for value in list) #[2,4,6]
Splat Arguments
引数の間にargs...的なやつを仕込める
loadTruck = (firstDibs, secondDibs, tooSlow..., leftAtHome) ->
truck:
driversSeat: firstDibs
passengerSeat: secondDibs
trunkBed: tooSlow
taxi:
passengerSeat: leftAtHome
loadTruck("Amanda", "Joel", "Bob", "Mary", "Phillip", "Austin")
# => { truck: { driversSeat: 'Amanda', passengerSeat: 'Joel', trunkBed: [ 'Bob', 'Mary', 'Phillip' ] }, taxi: { passengerSeat: 'Austin' } }
loadTruck("Amanda")
# => { truck: { driversSeat: "Amanda", passengerSeat: undefined, trunkBed: [] }, taxi: undefined }
jQueryのコンフリクトしないrequire
$ ?= require 'jquery' # For Node.js compatibility
Using Heregexes (複数行で書ける正規表現)
CoffeeScriptにはいい感じのがあるとか。コメントやwhitespaceを含めながら複雑な正規表現を書ける。
heredocumentっぽいからheregexesという名前なのかな。
pattern = ///
^\(?(\d{3})\)? # Capture area code, ignore optional parens
[-\s]?(\d{3}) # Capture prefix, ignore optional dash or space
-?(\d{4}) # Capture line-number, ignore optional dash
///
[area_code, prefix, line] = "(555)123-4567".match(pattern)[1..3]
# => ['555', '123', '4567']
closureの書き方 (Command Patternにて)
Command Patternのページに書いてあるけど、Command Patternはどうでもよくて、クロージャの書き方がいい感じ。
# Using a private variable to simulate external scripts or modules
incrementers = (() ->
privateVar = 0
singleIncrementer = () ->
privateVar += 1
doubleIncrementer = () ->
privateVar += 2
commands =
single: singleIncrementer
double: doubleIncrementer
value: -> privateVar
)()
class RunsAll
constructor: (@commands...) ->
run: -> command() for command in @commands
runner = new RunsAll(incrementers.single, incrementers.double, incrementers.single, incrementers.double)
runner.run()
incrementers.value() # => 6
Singleton (プライベート変数とプライベートクラス)
Private Classが使える。もちろん、外からは見えず、アクセスしようとしてもundefined
になる。
classのなかで @classVar: 'hoge
や instanceVar: hoge
などといった書き方ではなく、privateVar = 'hoge'
と書くことで、外に見えないプライベート変数を作っている。
class Singleton
# You can add statements inside the class definition
# which helps establish private scope (due to closures)
# instance is defined as null to force correct scope
instance = null
# Create a private class that we can initialize however
# defined inside this scope to force the use of the
# singleton class.
class PrivateClass
constructor: (@message) ->
echo: -> @message
# This is a static method used to either retrieve the
# instance or create a new one.
@get: (message) ->
instance ?= new PrivateClass(message)
a = Singleton.get "Hello A"
a.echo() # => "Hello A"
b = Singleton.get "Hello B"
b.echo() # => "Hello A"
Singleton.instance # => undefined
a.instance # => undefined
Singleton.PrivateClass # => undefined
なにしてるのかわかんないやつ
CoffeeScript Cookbook » Check if type of value is an Array
http://coffeescriptcookbook.com/chapters/arrays/check-type-is-array
- なんか高度なやつ
- 頭がおかしくなりそうな文
##なにしてるのかわかんないやつらは置いといて、いい感じの書き方を覚えたら、スタバでCoffeeでも飲んでレッツ!ドヤリング!