2
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

D3のコードをES5からES6に書き直す場合はthisの扱いに注意

はじめに

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

対策

  1. 従来のES5の文法でfunctionを定義
  2. d3で用意されている引数を利用

2のやりかた

d3.selectAll('.hoge')
  .each((d, i, nodes) => {
    const fuga = d3.select(nodes[i]);
    fuga.append('piyo')
    ...
  })

おわりに

ES5の関数定義 = ES6のアロー関数定義 とひとくくりに考えていたためハマってしまった。よくよく考えると、文と式の違いだからスコープが違うのは当たり前か。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
2
Help us understand the problem. What are the problem?