この記事はTech-Circle Hands on Advent Calendar 2016の2日目の記事です。
昨日はtominaga443さんのパワポでつくるスマホアプリ: CanvasFlipでインタラクティブなプロトタイピングでした。
引き続きフロントエンド週間ですが、今日はJavaScript行ってみましょう。
「JavaScript? うん、まぁ最近書いてないけど、ある程度は読み書きできるよ」
とか言っていたのもつかの間、新しめのコードを見てみるとES6(ES2015)、ES2016で追加された新しい記法に打ちのめされたりします。
ReactやらReduxやら、新しい技術はどんどん出てきますが、学ぶ際に記法で嵌っているとコアな部分に集中できないので、まずは新しい記法に慣れてしまいましょう。
わかってしまえば単なる便利記法なので難しくないです。
なお、React/Reduxのコードを読むうえで出会った箇所が主なため、一部の例はBabelによる次期ESの先取りとなります。
それでは、ググりづらい記号系をメインに進めていきましょう。
連想配列の省略表記
まずは手軽な物から。
keyとvalueが同名の場合、省略が可能になりました。
var sample = 42
{ sample: sample } // { sample: 42 }
const sample = 42
{ sample } // { sample: 42 }
配列からの展開
配列の値を変数に代入する際、まとめて代入ができるようになりました。
var list = [1, 2, 3]
var a = list[0]
var b = list[1]
const list = [1, 2, 3]
const [a, b] = list
関数から複数返り値を受け取ったりも。
const [result, isFinished] = execute()
連想配列からの展開
同様に連想配列にも使えます。配列からの代入よりはこっちの方がメジャーかも。
Reactのコードを読み書きしていると、this.props
からの代入でよくお世話になりますね。
var dictionary = {
url: 'http://www.example.com',
method: 'GET'
}
var url = dictionary.url
var method = dictionary.method
const dictionary = {
url: 'http://www.example.com',
method: 'GET'
}
const { url, method } = dictionary
深い階層からも取れます
const dictionary = {
url: 'http://www.example.com',
method: 'GET',
parameters: {
name: 'Sheile'
}
}
const { url, method, parameters: { name } } = dictionary
console.log(name) // Sheile
ただし、この場合parameters
は取れないので注意。
配列の展開
...
表記で配列の展開ができるようになりました。
var list = [1, 2, 3]
Math.max(list) // NaN これはダメ
Math.max.apply(null, list) // 3
const list = [1, 2, 3]
Math.max(...list) // 3
配列の結合
配列の途中で...
を使うことで配列の結合、挿入が手軽にできます。
const list = [2, 3, 4]
[1, ...list, 5] // [1, 2, 3, 4, 5]
連想配列の展開
前項の...
演算子は連想配列にも適用できる……ようになる予定です。
現在Stage3なので仕様は確定していますが、いま使うにはBabelなどのトランスパイラが必要になります。
ただ、Reduxのreducerを書いているとすごく多用するため、ここで紹介。
reducerでの使い方は既存のオブジェクトを活かしつつ、一部を書き換える用途なので、JavaScriptで言うとlodash.assign
、ES2015で言うとObject.assign
の代替ですね。
#Stage3って何?という方はこちらの記事がわかりやすいです
ES2016の追加機能が決定、あるいはES7言うな問題
var _ = require('lodash')
var state = { key: 'value', isFetching: true }
var newState = _.assign({}, state, { isFetching: false })
// { key: 'value', isFetching: false }
const state = { key: 'value', isFetching: true }
const newState = {
...state,
isFetching: false
} // { key: 'value', isFetching: false }
アロー関数(=>
)による関数定義
AltJS系ではおなじみ、アロー関数による関数定義もできるようになりました。
function output(key, value) {
console.log(key)
console.log(value)
}
output = (key, value) => {
console.log(key)
console.log(value)
}
見比べてみると対して違いは無いと思います。
function
がなくなって、匿名関数を変数に代入するようになっています。
記法の省略
前項の例だとあまり違いがありませんが、アロー関数は条件次第で記述の省略が可能です。
Array#map
など、引数に関数をとる場合はこの省略記法が良く使われるので慣れておきましょう。
[1, 2, 3].map(function (n) {
return n * 2
})
// [2, 4, 6]
// 引数1つなら (n) ではなく n でOK
// 関数内が単一式ならば {} や return は不要
[1, 2, 3].map(n => n * 2)
高階関数
では、ちょっとややこしい例を見てみましょう。
fetchData = token => dispatch => {
/* 省略 */
}
さて、これをfunction表記に戻すと?
#読み方に慣れた人は答えを見る前に考えてみても良いです
function fetchData(token) {
return function(dispatch) {
/* 省略 */
}
}
はい、こうなります。あってました?
thisの束縛
CoffeeScriptで->
と=>
を使っていた人にはお馴染みですが、アロー関数の場合、定義時のスコープでthisが束縛されます。
class
定義内の関数はこっちの方が使い勝手が良いですね。
$(function() {
function handleClick1() {
console.log(this) // <button>
}
handleClick2 = () => {
console.log(this) // document
}
$('button#button1').click(handleClick1)
$('button#button2').click(handleClick2)
})
handleClick = () => {
console.log(this)
}
that = this
function handleClick() {
console.log(that)
}
最後に
明日は色々な便利Chrome拡張を作っているtksugimotoさんです。