【coffeescript】存在確認演算子【?】
こんばんは.1000chです. 先週末,同期内定者とのチーム開発が一段落しました. 内定式でそれの発表など行いましたが,昨年のインターンに続き非常に良い経験でした. 気が向いたらそのうち記事にまとめます.
この開発のなかで自分は主にフロントを扱っており,実はその影響から最近coffeescriptの記事が多いかったりしてます. 今回もその流れでcoffeescriptネタを1ついきますね.
存在確認演算子
coffeescriptの機能の中で,個人的に「慣れたら便利なんだけどいまいち使い方よくわからんな」と思っていたのが,存在確認識別子 の 「?」です.
そもそものjavascriptには無い機能なので,慣れるまで取っ付きにくいものかと思います.
(どうやらrubyにおける?
に似ているようですが)
一言で言うと「そのプロパティが存在するかどうか」を判断した上で,「続く処理を行うかどうか」を選択できる機能というところですが... まぁわかりにくいですね.実際に見ていくのが早そうです.
javascriptにおける?
まずjavascriptにおける?
といえば
var result = flag ? "flag on" : "flag off";
みたいな感じで,いわゆる三項演算子として使いますよね.
しかし,cofffescriptにおいてはこの目的で?
を使うことはできません.
三項演算子的な表現をする場合は,
# flagには適当なbool値を与える result = if flag then "flag on" else "flag off"
// コンパイル後 var result; result = flag ? "flag on" : "flag off";
というように,if文を1行で書く形で実現します. より自然言語としての英語に近い表現ですね.
coffeescriptにおける?
さて,ではいよいよcoffeescript風に?
を使ってみましょう.
参考はこちら.
The Little Book on CoffeeScript - Syntax
いわく,
CoffeeScriptの存在確認演算子である?は変数がnullでないか、undefinedでなければtrueを返します。
とのことです. 実際に触ってみましょう.
# null,undefined は false console.log null? #false console.log undefined? #false # 未定義変数もfalse console.log undefined_variable? #false # その他はtrue console.log 0? #true console.log false? #true console.log ""? #true # 二重につけると.. console.log null?? #true (false?と等しい.使い道ないかも)
null
,undefined
の場合は変数が存在しないとしてfalse
が返りますが,その他false
と判断されるような変数(ex.false
,0
)に関しては「オブジェクト自体は存在する」為,true
が返ってくるようですね.これが,存在確認演算子と呼ばれる所以でしょう.
もう一つ,オブジェクトに対して利用した例を見てみましょう.
#オブジェクトに対する利用 myObj = a: "prop_a" b: b1: "prop_b1" b2: "prop_b2" console.log myObj? #true console.log myObj.a? #true console.log myObj.b? #true console.log myObj.c? #false console.log myObj.b.b1? #true console.log myObj.b.b2? #true #console.log myObj.c.b2? #TypeError: Cannot read property 'b2' of undefined console.log myObj.c?.b #undefined
ここで注目すべきは,存在しないプロパティc周りの処理です.通常myObj.c.b
というよう処理を書いてしまうと,undefined.b
と同値になり,TypeErrorの例外が発生してしまいます.
そこでmyObj.c?.b
と記述すると,myObj.c
でundefined
と判定された時点で,undefined
を返してくれるようになります.コレを応用すると取得したデータを扱う際に,プロパティの存在確認をしつつ,存在するときのみ値を返す,という記述もできます.
console.log myObj.b?.b1 #prop_b1 console.log myObj.c?.b1 #undefined
同様に,メソッドを持つときのみ実行,ということも可能です.
論理演算子としての?
ここが自分が「?
ってよくわからんな」と思ったポイントでもあるのですが,coffeescriptはにおける?
は論理演算子としても利用することができます.実例を見てみましょう.
console.log 2 || 3 # 2 console.log 2 or 3 # 2 console.log 2 ? 3 # 2 console.log null || 3 #3 console.log null or 3 #3 console.log null ? 3 #3
ただし注意が必要なのは,存在確認演算子に置いては,0
,''
,false
などはtrue
と評価される点です.
console.log false || 3 #3 console.log false or 3 #3 console.log false ? 3 #false console.log 0 || 3 #3 console.log 0 or 3 #3 console.log 0 ? 3 #0
改めて確認しておくと,?
においてfalse
と評価されるのは null
およびundefined
のみです.
拡張論理演算子としての?=
coffeescriptでは論理演算子の拡張としてvar1 ||= var2
という表現を利用できます.var1を評価し,falseとなったときのみ,var1にvar2を代入することができます.
a = 0 a ||= 1 # a or= 1 ともかける console.log a #1
var a;
a = 0;
a || (a = 1);
console.log(a);
しかしこれでは,aがfalseと評価される際に常に書き換えられてしまいます. 例えば「オブジェクトにプロパティが存在しない時のみデフォルト値をセット」という表現がやりづらいです. つまり,プロパティとして0や空文字を持つ場合もデフォルト値に書き換えてしまうのです.
そこで利用できるのが,?=
という表記です.
流れ的にお分かりかと思いますが,存在確認演算子によってfalseと判定される場合のみ代入することが可能となります.
# ?= のデモ obj = a: 0 b: b1:1 b2:2 console.log obj # { a: 0, b: { b1: 1, b2: 2 } } obj.a ?= 1 # obj.a は既に存在するので書き換えられない obj.c ?= 3 # obj.c は存在しないので,新規プロパティの追加 console.log obj # { a: 0, b: { b1: 1, b2: 2 }, c: 3 }
まとめ
coffeescriptにおける存在確認演算子?
の使い方をまとめました.