4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

LinkbalAdvent Calendar 2018

Day 4

letをconstにできるケース(とlet使用禁止というルールについて)

Last updated at Posted at 2018-12-04

JavaScript(ES6〜)には、値を再代入できる変数宣言「let」とできない「const」があります。

この記事では、letをconstにできるケース(再代入を行う実装を、再代入なしで実現できるケース)をいくつかまとめてみたいと思います。

※「書き換え後のように実装しましょう!」という記事ではありません

(let使用禁止についての記述は一番下です)

letをconstにできるケース

三項演算子にする

条件分岐によって代入内容を変えたいです。

let result = 'foo'
if (isBar) {
  result = 'bar'
}

三項演算子にできます。


const result = isBar ? 'bar' : 'foo'

関数化する

さっきよりもたくさんの条件分岐によって、値を変えたいです。

let result = 'default'
if (key === 'F') {
  result = 'foo'
} else if (key === 'B') {
  result = 'bar'
} else if (key === 'Z') {
  result = 'baz'
}

処理を分割する目的も含めて関数化で解決できそうです。

const getNameByKey = key => {
  switch (key) {
    case 'F': return 'foo'
    case 'B': return 'bar'
    case 'Z': return 'baz'
    default: return 'default'
  }
}
const result = getNameByKey(key)

即時関数でもよいと思います。

※もしまんま例の様な変換するだけの分岐であればObjectや配列などで対応表が作れそうです。

const FBZ_DATA = { F: 'foo', B: 'bar', Z: 'baz' }
const result = (key in FBZ_DATA) ? FBZ_DATA[key] : 'default'
const arr = [{ key: 'F', name: 'foo' }, { key: 'B', name: 'bar' }, ...]
const data = arr.find(v => v.key === key)
const result = data ? data.name : 'default'

再帰処理にする

1から10までループしながら何かしたいです。

for (let i = 1; i <= 10; i++) {
  console.log(i)
}

再帰処理でもできそうです。

const echoNum = (current, max) => {
  console.log(current)
  if (current < max) echoNum(current + 1, max)
}
echoNum(1, 10)

Arrayの関数を使う

Web開発だと可変長のデータを回すことは頻繁にあっても、さっきのようなn回ループって滅多にないですね。

というわけでデータを回したいとき。

const users = [
  { id: 1, gender: 'male', money: 100 },
  { id: 2, gender: 'female', money: 200 },
  { id: 3, gender: 'male', money: 300 },
  { id: 4, gender: 'female', money: 400 },
  { id: 5, gender: 'male', money: 500 }
]

上記のデータからgenderがmaleである行のmoneyの合計を出したいです。

let money = 0
for (const user of users) {
  if (user.gender === 'male') money += user.money
}

僕はArrayの高階関数が好きです。filterreduceの2つを使ってみます。

const money = users.filter(u => u.gender === 'male').reduce((acc, u) => acc + u.money, 0)

余談:let使用禁止というルール

letを一切使わずに実装することは可能で、実際に僕の書いているプロジェクトではconstしか使っていません。
元々そういうルールがあったわけではなく、コードレビューを重ねていくなかで自然とそうなりました。

しかし、冒頭で書いたように、そうすべきだと主張したいわけではありません。

最後の例のgender=maleのmoneyを合計する処理なんかは、慣れていない人にとってはletを使ったパターンのほうが何をやっているか分かりやすいと思います。

以前、実装メンバーのレベルにばらつきがあるチームで書いていたとき、「var、let禁止」というルールがありました。
ですが、あるメンバーが、実現したいことをconstを使って書くことができず、下記のようなコードが生まれてしまったことがありました。

const result = { flag: false }
if (isHoge) result.flag = true

(result自体には再代入できないけれど、resultが参照するオブジェクトの値なら変更できる、という性質を利用してletのような使い方をしている)

もともとは安全なコードを書くために設けられたルールであったと思うのですが、上記の例ではそれを実現できていません。

ルールを設けただけではメンバーのレベル(あるいは思想や好み)の差を埋めることは難しいです。
もし「let禁止」のようなルールを作るのであれば、なぜそうすると安全であるか、どう書けばそれが実現できるのか、まで理解・納得してもらってからがよいと思います。

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?