Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

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のアロー関数定義 とひとくくりに考えていたためハマってしまった。よくよく考えると、文と式の違いだからスコープが違うのは当たり前か。

icchi_h
都内のメディア企業で働く高専出身エンジニア
https://icchi.me
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