Edited at

JavaScript おじさんが教える本当の Modern JavaScript 入門 2 「const, immutable, functional programming」

More than 1 year has passed since last update.


シリーズ概要


Phase 1 のまとめ


  • Parcel で module system が使えるようになった。

  • Parcel で Babel の処理をしてくれるので、ES2015+ syntax で JS を書くことができるようなった。

  • Parcel が勝手に JSX も処理してくれるので React コンポーネントを JSX で書けるようになった。

  • Prettier でコードが成形できるようになった。


Phase 2

モダンなパラダイムで JavaScript を書く


  • var, let を書かないで、ほぼ全部 const にする

  • immutable にする

  • そのためには functional programming に則っていく必要あり。
    map, reduce 等をうまく使う。


Phase 3 の展望

非同期処理をモダンに書く


  • Callback の根絶

  • Promise の理解

  • async / await を使う

  • redux/vuex 関係でも async/await を使う


Phase 4 の展望

Virtual DOM を用いた View ライブラリの活用


  • ReactJS

  • VueJS

  • Redux/Vuex


モダンなパラダイムで JavaScript を書く


  • 全て const を使う(くらいの気持ちで)

  • Immutable にする(Object の property, Array の要素を変更しない)

  • Functional Programming を意識する

Immutable にすることを意識すれば、結果として上記三つを満たすことになる。


const を基本的に使う


  • 全て const でかく(くらいの気持ちで)

  • var は使うケースはないと考えていい

  • let もほぼほぼ使わない

変数を宣言する場合には、基本的に const を使用する。const は再代入を受け付けない。


関数の場合

https://codesandbox.io/s/jj2lklyk7w

関数を再代入する必要があるケースはほぼない。そのため const を使う。

もし関数を再代入する必要があるとすれば、その構造自体を再検討する必要がある。

// 関数宣言 (function declaration) を使用した場合

// 関数の巻き上げ (function hoisting) が起きてしまう
// これはしない方がいい
// 可読性が低いため

func1()

function func1() {
console.log('func1')
}

// 関数式(function expression) で定義した場合
// 関数の巻き上げは起きない
// 望ましい
try {
func2()
} catch (err) {
console.error(err.message)
}

var func2 = function() {
console.log('func2')
}

// (特殊なケースを除けば)
// 関数を再代入することは避けた方がいいので
// 再代入を禁止する const を使用する方が良い
// また arrow function を使った方がよい
const func3 = () => {
console.log('func4')
}

func3()

// async を使いたい場合には、
// 以下のように書けばいい
const promiseFunc = val => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(val)
}, 1000)
})
}

const func5 = async () => {
const val = await promiseFunc('start promise')
console.log(val)
}

func5()


配列に push していくパターンもやめる

(どちらかというと後ほど取り上げる immutable のテーマだが)

https://codesandbox.io/s/j4ollpp2mw

// よくみるがあまり良くない例

// からの配列を宣言しておいて、後からそれに追加するパターン
var array1 = [1, 2, 3, 4]
var array2 = []

for (var i = 0; i < array1.length; i++) {
array2.push(array1[i] + i)
}

console.log(array2)

// map を使えば全て const で宣言できる
const array3 = [1, 2, 3, 4]
const array4 = array3.map((o, index) => o + index)

console.log(array4)


Object の場合

(これも配列の場合と同じく、immutable が主テーマだが)

const obj1 = { name: 'nakanishi', id: 1 }

// property を書き換える場合には次のようにする
// 実際には書き換えているのではなく、新しいオブジェクトを作成している
const obj2 = { ...obj1, name: 'sasaki' }

console.log(obj1, obj2)


Immutable にする

https://codesandbox.io/s/xrp6lqz57w


  • Object のプロパティを変更しない

  • Array の要素を変更しない

  • 新しい object, array を生成する

// object を deep freeze させる

// => mutation が起きる場合、エラーを吐く
import deepFreeze from 'deep-freeze'

// object の場合
const obj1 = { name: 'nakanishi', id: 1 }
deepFreeze(obj1)

// property を書き換える場合には次のようにする
// 実際には書き換えているのではなく、新しいオブジェクトを作成している
const obj2 = { ...obj1, name: 'sasaki' }

console.log(obj1, obj2)

// deepFreeze させているので、
// property を書き換えるとエラーが出る
try {
obj1.name = 'sasaki'
} catch (err) {
console.error(err.message)
}

// 配列の場合
const array1 = []
deepFreeze(array1)

// 配列の要素を書き換える場合には次のようにする
// 実際には書き換えているのではなく、新しい配列を作成している
const array2 = [...array1, 'test']
console.log(array1, array2)

try {
// deepFreeze させているので、
// 配列の要素を書き換えるとエラーが出る
array1.push('test')
} catch (err) {
console.error(err.message)
}

const array3 = [1, 2, 3]

try {
// deepFreeze させているので、
// 配列の要素を書き換えるとエラーが出る
array1[0] = 'test'
} catch (err) {
console.error(err.message)
}

// Object の property を削除する方法
const person = {
name: 'John',
password: '123',
age: 28,
}

deepFreeze(person)

// 特定の key を削除する関数
const delteObjectKey = (object, deleteTargetKey) => {
return Object.keys(object).reduce((obj, key) => {
if (key !== deleteTargetKey) {
return { ...obj, [key]: person[key] }
}
return obj
}, {})
}

// person オブジェクトから age という key を削除する
const newPerson = delteObjectKey(person, 'age')

console.log(newPerson)

try {
// deepFreeze させているので、
// プロパティを削除するとエラーが出る
delete person.age
} catch (err) {
console.error(err.message)
}


Functional Programming を意識する

map, reduce 等をうまく使う。

詳しくは手前味噌ですみませんが、次の記事を参照してください。

JavaScript おじさんが教える ES2015+ と関数型プログラミング 1


まとめ

以下の三つを守って、可読性が高く、変更に強い JavaScript を書く。


  • 全て const を使う(くらいの気持ちで)

  • Immutable にする(Object の property, Array の要素を変更しない)

  • Functional Programming を意識する