はじめに
ES5書かれていたd3のコードをES6に書き直した際に、文法的には間違っていないのにエラーが発生したのでメモ。
問題
selectAll()
で取得した要素をeach()
でループ処理する際に、各要素を適切に取得できていなかった。
エラー箇所
修正後
d3.selectAll('.hoge')
.each(d => {
const fuga = d3.select(this); // DOM内にhogeクラスはあるのに変数fugaがundefinedてしまう
fuga.append('piyo')
...
})
修正前
d3.selectAll('.hoge')
.each(function(d) {
const fuga = d3.select(this); // DOM内にhogeクラスはあるのに変数fugaがundefinedてしまう
fuga.append('piyo')
...
})
エラー内容
d3 select this createElementNS' of undefined"
select()
で要素が適切に取得できていないため、DOM操作に失敗していた。
原因
アロー関数内のthis
はスコープが従来と異なるため
詳細は以下の記事に詳しく書いてありました。
アロー関数はthisの値を語彙的に束縛する”らしい @ Qiita
対策
- 従来のES5の文法で
function
を定義 - d3で用意されている引数を利用
2のやりかた
d3.selectAll('.hoge')
.each((d, i, nodes) => {
const fuga = d3.select(nodes[i]);
fuga.append('piyo')
...
})
おわりに
ES5の関数定義 = ES6のアロー関数定義
とひとくくりに考えていたためハマってしまった。よくよく考えると、文と式の違いだからスコープが違うのは当たり前か。