はじめに
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の値を語彙的に束縛する”らしい] (https://qiita.com/mejileben/items/69e5facdb60781927929#%E3%82%A2%E3%83%AD%E3%83%BC%E9%96%A2%E6%95%B0%E3%81%AFthis%E3%81%AE%E5%80%A4%E3%82%92%E8%AA%9E%E5%BD%99%E7%9A%84%E3%81%AB%E6%9D%9F%E7%B8%9B%E3%81%99%E3%82%8B%E3%82%89%E3%81%97%E3%81%84) @ Qiita
対策
- 従来のES5の文法で
function
を定義 - d3で用意されている引数を利用
2のやりかた
d3.selectAll('.hoge')
.each((d, i, nodes) => {
const fuga = d3.select(nodes[i]);
fuga.append('piyo')
...
})
おわりに
ES5の関数定義 = ES6のアロー関数定義
とひとくくりに考えていたためハマってしまった。よくよく考えると、文と式の違いだからスコープが違うのは当たり前か。