2

While trying to write some awesome JS I ran into some strange JS-behaviour. I've created a piece of code to demonstrate my problem:

http://jsfiddle.net/CeyCy/

<html>
  <head>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() {
      var images = $('.images').children();
      var filtered = images.filter(function(i, image) {
        console.log(this);
      }, "abc");
    });
    </script>
  </head>
  <body>
    <div class="options">
      <div class="filters">
      </div>
      <ol class="pagination">
      </ol>
    </div>
    <div class="results">
      <ul class="images">
        <li data-category="Zakelijk">Result 1</li>
        <li data-category="Speels">Result 2</li>
        <li data-category="Blogging">Result 3</li>
        <li data-category="Zakelijk">Result 4</li>
        <li data-category="Speels">Result 5</li>
        <li data-category="Blogging">Result 6</li>
        <li data-category="Zakelijk">Result 7</li>
        <li data-category="Speels">Result 8</li>
        <li data-category="Blogging">Result 9</li>
        <li data-category="Zakelijk">Result 10</li>
        <li data-category="Speels">Result 11</li>
        <li data-category="Blogging">Result 12</li>
        <li data-category="Zakelijk">Result 13</li>
        <li data-category="Speels">Result 14</li>
        <li data-category="Blogging">Result 15</li>
      </ul>
    </div>
  </body>
</html>

Ok, now my question. When using the Array.filter method you pass in a callback function as first parameter and an optional context as second parameter. As you can see, I'm passing "abc" as context (which is ridiculous, ofcourse). I would expect my console to throw a lot of "abc", but instead it prints the jQuery elements!

Can someone shine some light on this please?

Thanks,

Martijn

1
  • 4
    You're not using the Javascript Array.filter(), you're using jQuery's .filter() Commented Jul 24, 2012 at 14:15

1 Answer 1

6

As you can see, I'm passing "abc" as context (which is ridiculous, ofcourse). I would expect my console to throw a lot of "abc", but instead it prints the jQuery elements!

You're using jQuery's filter, which doesn't have a context parameter, rather than ES5's Array#filter, because you're calling filter on a jQuery object, and jQuery objects are not arrays (although they offer a lot of array-like functionality, and several "methods" with similar names — including filter).

Three options for you:

makeArray

You can use jQuery's makeArray to turn the jQuery object into an array, e.g.:

$(function() {
  var images = $.makeArray($('.images').children());
  var filtered = images.filter(function(i, image) {
    console.log(this);
  }, "abc");
});

Updated fiddle

proxy / bind

Or alternately, you can use jQuery's proxy function (or ES5's Function#bind) to bind the iterator function you're passing to jQuery's filter so it ignores the this jQuery supplies:

$(function() {
  var images = $('.images').children();
  var filtered = images.filter($.proxy(function(i, image) {
    console.log(this);
  }, "abc"));
});

Apply Array#filter to the jQuery object

Or you can apply Array#filter directly to the jQuery object:

$(function() {
  var images = $('.images').children();
  var filtered = Array.prototype.filter.call(images, function(i, image) {
    console.log(this);
  }, "abc");
});

...since Array#filter is expressly defined to work on anything array-like, not just Arrays. That last might actually be the most efficient way to do it. Fiddle

Sign up to request clarification or add additional context in comments.

4 Comments

Ah crap, thanks.. have had the same issue (using jQuery methods instead of plain-old-javascript methods) several times now >.<
@MartijnDwars: LOL no worries, glad that helped. I added two more options for you, the last of which avoids creating unnecessary temporary objects.
Thanks for the extensive explanation! It really helps a lot when getting familiar with JS & jQuery.
@MartijnDwars: You're welcome! If you're interested in learning more about JS, I blog about it periodically.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.