JavaScript
CoffeeScript

CoffeeScript Cookbookのおいしいところだけ抜き出して、おいしい思いをしよう!!

More than 5 years have passed since last update.

Cookbookがあった。

CoffeeScript Cookbook

Cookbookとは「諸々の問題を華麗に解決しよう!」というレシピ本みたいなの。CoffeeScriptの特徴というより、単なるプログラムの書き方の寄せ集めみたいなノリでもある。

なので、CoffeeScriptの特徴を捉えてるやつをピックアップして見てみよう!


スルーしてるやつ


  • 公式ドキュメントに載ってる基本的なものはだいたいスルー

  • あと変態ぽいやつ(例えば「Repeating a String」)もスルー。(直感的でない)

  • 単純なjsのtipsもスルー (Recursive Functions)


スタティックなメソッドを使おう

http://coffeescriptcookbook.com/chapters/classes_and_objects/class-methods-and-instance-methods

なぜか公式に書いてない、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++


ディープコピー

http://coffeescriptcookbook.com/chapters/classes_and_objects/cloning

ガチでディープコピーするとき。

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

http://coffeescriptcookbook.com/chapters/functions/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 (複数行で書ける正規表現)

http://coffeescriptcookbook.com/chapters/regular_expressions/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 (プライベート変数とプライベートクラス)

http://coffeescriptcookbook.com/chapters/design_patterns/singleton

Private Classが使える。もちろん、外からは見えず、アクセスしようとしてもundefinedになる。

classのなかで @classVar: 'hogeinstanceVar: 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でも飲んでレッツ!ドヤリング!

ドヤリング