4

I am just curious as to why d3.select("svg") == d3.select("svg") resolves to false and not true.

With D3 loaded in my browser (I tried chrome and FF), I typed that line into the console and it gave me that surprising result.

I used D3 version 5

The html body looks like this:

<body>
<svg></svg>
</body>
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
namjo
  • 63
  • 7
  • Why do you expect another result? – Nico Haase Jul 09 '19 at 14:39
  • They are the same selections after all. In fact, I assigned `a = d3.select("svg")` and `b = d3.select("svg")` and I for some reason I had sth like `const foo = d3.local(); foo.set(a, 561); foo.get(b) // wished this would be 561 but in actuality it's undefined` – namjo Jul 09 '19 at 14:49
  • 3
    Well, I think both might be instances of an object with the same information, but not the same objects – Nico Haase Jul 09 '19 at 14:49
  • As a general rule of thumb, you should use `===` when comparing objects in JS. You can read more about it [here](https://stackoverflow.com/a/523647/1913185) – technogeek1995 Jul 09 '19 at 15:03
  • 1
    @technogeek1995 indeed, as a rule of thumb, one should always use `===` in JavasCript. However, in this case (comparing objects), it'd make no difference. – Gerardo Furtado Jul 10 '19 at 02:21

2 Answers2

4

The other answer provides an alternative (and the correct one by the way) to your problem. My goal here is to explain why you got the false.

This boils down to the old and famous case of comparing objects ({} !== {}) in JavaScript:

console.log({} === {})

You can read more about this subject by looking at the answers to this question and this question. The first answer to this question is also quite interesting and didactic.

Back to D3:

In D3 v3 and below selections are arrays, while in D3 v4 and above (like V5, the one you're using), selections are objects. Both will return object for typeof:

const svg = d3.select("svg");
console.log(typeof svg)
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>

And, in both cases (arrays or objects), the comparison will return false.

Because of that, even if two different selections point to the same DOM element, the selections themselves, which are objects, are different:

const svg1 = d3.select("svg");
const svg2 = d3.select("svg")
console.log(svg1 === svg2)
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>

Finally, regarding your comment, you're using the local variable wrong: you have to set it to the node, not to the selection. The API is clear:

local.set(node, value) <>

Sets the value of this local on the specified node to the value, and returns the specified value. (emphasis mine)

If you use it correctly, it will work:

const a = d3.select("svg");
const b = d3.select("svg");
const local = d3.local();
local.set(a.node(), 561);
console.log(local.get(b.node()))
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>
Community
  • 1
  • 1
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
  • Thanks. Even though Aswin Kumars answer was helpful too, this post gives a good explanation from the bottom up. – namjo Jul 10 '19 at 08:12
3

Use node()

d3.select("svg") - return d3 selection object
d3.select("svg").node() - return DOM node

console.log(d3.select("svg") == d3.select("svg"))

console.log(d3.select("svg").node() == d3.select("svg").node())
<script src="//d3js.org/d3.v4.0.0-alpha.23.min.js"></script>

<svg></svg>
User863
  • 19,346
  • 2
  • 17
  • 41