title: d3 filter selection not working?
body: <p>Either I am not using d3's <a href="https://github.com/mbostock/d3/wiki/Selections#filter" rel="noreferrer">selection.filter</a> correctly, or it is buggy. I can distill the issue to a few lines. I'm in the Chrome debugger with d3 loaded. Let's start with an empty selection</p>
  
  <pre><code>d3.selectAll("nonexistant").empty()
  &gt; true
  </code></pre>
  
  <p>and bind some data to it.</p>
  
  <pre><code>d3.selectAll("nonexistant").data([1,2,3,4])
  &gt; [Array[4]]
  </code></pre>
  
  <p>Good, so it has size four. Let's check with <a href="https://github.com/mbostock/d3/wiki/Selections#size" rel="noreferrer">selection.size</a>:</p>
  
  <pre><code>d3.selectAll("nonexistant").data([1,2,3,4]).size()
  &gt; 0
  </code></pre>
  
  <p>Hmm, I guess that's because <s>there are no DOM elements yet</s> the update selection is empty since there were no previous elements. So let's <s>make</s> access the enter selection.</p>
  
  <pre><code>d3.selectAll("nonexistant").data([1,2,3,4]).enter()
  &gt; [Array[4]]
  d3.selectAll("nonexistant").data([1,2,3,4]).enter().size()
  &gt; TypeError: undefined is not a function
  d3.selectAll("nonexistant").data([1,2,3,4]).enter().append("p").size()
  &gt; 4
  </code></pre>
  
  <p>Not sure why the enter selection causes an error, <strong>(UPDATE: Fixed in v3.4.12)</strong> but anyway, if we try filtering using the example function in the docs,</p>
  
  <pre><code>function odds(d, i) { return i &amp; 1; }
  d3.selectAll("nonexistant").data([1,2,3,4]).filter(odds);
  &gt; [Array[0]]
  d3.selectAll("nonexistant").data([1,2,3,4]).enter().filter(odds);
  &gt; []
  d3.selectAll("nonexistant").data([1,2,3,4]).enter().append("p").filter(odds)
  &gt; [Array[2]]
  </code></pre>
  
  <p>Why is it silently filtering out all elements when there are no DOM elements bound? It does seem to be working when I already have DOM elements. But that feels pretty useless, since I don't want to create elements for data I'm discarding. Maybe if I put the filter earlier?</p>
  
  <pre><code>d3.selectAll("nonexistant").data([1,2,3,4]).filter(odds).enter().append("p").size()
  &gt; TypeError: undefined is not a function
  d3.selectAll("nonexistant").data([1,2,3,4]).enter().filter(odds).append("p").size()
  &gt; TypeError: undefined is not a function
  </code></pre>
  
  <p>Nope. It seems the way to go is with JS's native <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter" rel="noreferrer">filter</a> on arrays:</p>
  
  <pre><code>d3.selectAll("nonexistant").data([1,2,3,4].filter(odds)).enter().append("p").size()
  &gt; 2
  </code></pre>
  
  <p>The d3 docs do not seem to differentiate between selections that have DOM elements bound and those that do not. It seems that I should be able to stick <code>filter</code> anywhere in my method chain (and call <code>size</code> on any selection), and get the correct result without a type error. Granted, <code>filter</code> also supports CSS selectors that will require DOM elements, but I'm not using them here.</p>
  
  <p><em>What I want to know:</em> There is a mismatch between what d3 is doing and what I expect. To what extent am I harboring misconceptions about selections and what operations are valid on them? To what extent is the documentation unclear? Does any of this behavior qualify as a bug?</p>