11
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

知ってるとかっこよくなれるJS小技集2019

はじめに

コードレビューでさらっと
「こんな書き方もできますよ」って言ってくれる先輩ってかっこいいですよね。
いつかそんな先輩になれるように、メモ化しておこうという試みです。クリスマスのお供にどうぞ。

記法

変数名が同じなら省略できる

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'}こういうのです。配列のようにスッキリは書けないので一工夫必要になります。

そろそろネタがなくなって極小ネタになってきたので、また来年に向けて溜め直してきます!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
11
Help us understand the problem. What are the problem?