Posted at
LinkbalDay 4

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

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
}

僕はjsの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禁止」のようなルールを作るのであれば、なぜそうすると安全であるか、どう書けばそれが実現できるのか、まで理解・納得してもらってからがよいと思います。