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