はじめに
コードレビューでさらっと
「こんな書き方もできますよ」って言ってくれる先輩ってかっこいいですよね。
いつかそんな先輩になれるように、メモ化しておこうという試みです。クリスマスのお供にどうぞ。
記法
変数名が同じなら省略できる
const params = {
id: id
name: name
}
const params = {
id,
name
}
{}で分割代入
似てるものでこういう省略系もあります。分割代入と言うらしいです。
const id = response.id;
const {id} = response;
複数もOK
const {id, name} = response;
実務でよくみる使い方だと、Reactでpropsから値取り出すときとかでしょうか。
const {width, height} = props;
return (
<div style={{ width, height }} />
)
スプレッド演算子...で展開できる
const hoge = {
id: fuga.id,
name: fuga.name,
type: fuga.type
}
const hoge = {
...fuga
}
展開してさらに追加してもOK
const hoge = {
...fuga,
date: Date.now()
}
実例だと、ReduxでStateを一部更新するときなんかに使えますね
[HogeAction.SOMETHING]: (state: IHogeState, action: any): IHogeState => ({
...state,
fuga: action.payload
})
オブジェクトをコピーするためにも使えますが、Object.assign同様ディープコピーではないので注意です。
const original = {
id: 1,
obj: {
name: "shwan"
}
};
const copy = { ...original };
console.log(copy.obj.name); // "shwan"
original.obj.name = "changed";
console.log(copy.obj.name); // "changed"
オブジェクトのディープコピー技だとこんなのもありますが、undefindを扱えない罠があったりするので、できるだけ避ける人生を歩みたいですね。
const copy = JSON.parse(JSON.stringify(original));
スプレッド演算子に話をもどすと、引数でも展開できたりします。使う場面はあまりなさそうですが。
doSomething(fuga.id, fuga.name, fuga.type);
doSomething(...fuga);
条件分岐
論理演算子 || で条件分岐
let name;
if (response.name) {
name = response.name
} else {
name = 'Guest';
}
const name = response.name || 'Guest';
nullかもしれない配列を空配列にするときによく使います
response.names.forEach() // response.namesがnullやundefindだとエラー
const arr = response.names || [];
arr.forEach()
論理演算子 && で条件分岐
if (isGuest) {
doSomething();
}
isGuest && doSomething();
この記法、 if( A && B )
if( A || B )
なときと違う動きをしてるようにも見えますが
&&
は 左が偽なら左の値を、真なら右の値を返す
||
は 左が真なら左の値を、偽なら右の値を返す
という共通の仕組みです。
const name = response.name || 'Guest';
の例ではresponse.name
が'shwan'
などの文字列であれば左が真とみなせるので、左の値が返り、''
やnull
であれば、偽なのでGuest
が返ります。
キャスト
論理否定演算子 ! でのbooleanキャスト
const isSelected = this.state.type ? true : false;
const isSelected = !!this.state.type;
この記法も!を2つつなげると if(!isSelected)
なときと違う用法にみえますが、
どちらも同じ論理否定演算子で、値を真偽値とみなしたうえで真偽を反転する という動きをしています。
+ でのnumberキャスト
const id = '1'
console.log(+id); // 1
console.log(new Date()); // Wed Nov 27 2019 21:00:38 GMT+0900 (日本標準時)
console.log(+new Date()); // 1574856056863
キャストできなければNaN
になるので使い所は見きわめましょう。
ちなみにnew DateはDate.now()を使えばキャストせずとも数値で出せます。
console.log(Date.now()); // 1574856056863
letしない
三項演算子でletの回避
let type = 'a';
if (isB) {
type = 'b';
}
const type = isB ? 'b' :'a';
即時関数でletの回避
複雑な分岐なら即時関数を使って回避することもできますね。このあたりは可読性とトレードオフでしょうか。
const type = ((flag) => {
if (flag) {
return 'a';
} else {
return fukuzatuNaSomething();
}
})(isB);
その他Tips
関数の引数に初期値を設定する
初期値をつけておけば条件分岐を減らせます
const doSomething = (a, b = 1) => a * b;
doSomething(1); // 1
doSomething(1, 2); // 2
someで繰り返し処理を途中で抜ける
arr.forEach((obj) => {
doSomething
if(shouldBreak){
//break; ←できない
}
})
arr.some((obj) => {
doSomething
if (shouldBreak) {
return true;
}
return false;
})
someで配列の中を調べる
includes代わりに使えます
const arr = ['a', 'b', 'c'];
arr.includes('b') // true
const arr = [{
name: 'shwan'
},{
name: 'taro'
}];
arr.some((person) => person.name === 'shwan') // true
対象が配列なのか調べる
Array.isArray(target)
対象がオブジェクトなのか調べる
Object.prototype.toString.call(target).slice(8, -1).toLowerCase() === 'object';
ここでいうオブジェクトは {id: 1, name:'a'}
こういうのです。配列のようにスッキリは書けないので一工夫必要になります。
そろそろネタがなくなって極小ネタになってきたので、また来年に向けて溜め直してきます!