16
18

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 5 years have passed since last update.

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

Last updated at Posted at 2018-09-18

n8085ba48df1cb670.jpg

シリーズ概要

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 は再代入を受け付けない。

関数の場合

関数を再代入する必要があるケースはほぼない。そのため 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 のテーマだが)

// よくみるがあまり良くない例
// からの配列を宣言しておいて、後からそれに追加するパターン
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 にする

  • 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 を意識する
16
18
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
16
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?