1

In this function,

template.find('.userPhoto img').error(function () { 
    $(this)[0].src = '/images/default.png'; 
}).attr('src', image);

I was expecting $(this) to refer to an individual element, but it's not; instead, it's referring to a wrapped set... can you spot why?

Thanks!

ataddeini
  • 4,931
  • 26
  • 34
Ariel
  • 5,752
  • 5
  • 49
  • 59
  • 2
    Because that's what $(...) means. – asawyer Mar 09 '12 at 16:19
  • 7
    FWIW, `$(this)[0] === this` – Alnitak Mar 09 '12 at 16:20
  • 1
    How do you know it's a set? THe `[0]` addresses the DOM element of the jQuery object, not the first element – Pekka Mar 09 '12 at 16:21
  • So tempting to answer "Yes, cause I've googled it..." – IOrlandoni Mar 09 '12 at 16:21
  • @Pekka: Can you tell me which part of jquery makes sure that when you get [0] you'll actually get DOM element? – Martin. Mar 09 '12 at 16:23
  • @Martin I don't know the exact line number in the code that does it, but it is the convention that the original DOM node is stored in `.0` (or `[0]`). It doesn't look like a great choice, as it can confuse people (as this question shows) but maybe they had a reason for it – Pekka Mar 09 '12 at 16:24
  • @Martin. that's just how it works. Unless for some reason you generated an empty set. – Alnitak Mar 09 '12 at 16:24
  • @Pekka: [got it](https://gist.github.com/75d4dacefc154f4e00b6). Am I correct? – Martin. Mar 09 '12 at 16:25
  • 1
    @Pekka there's no such convention - a jQuery object when accessed like an array, gives you all of the elements matching the selector. If the object passed to the `$()` constructor was a DOM element then what you get is a jQuery object with _one_ element in it. – Alnitak Mar 09 '12 at 16:25
  • @Alnitak that's a different issue, isn't it? In the code above, `$(this)` will always return *one* jQuery object. That object's member `[0]` is the actual, native DOM element. The code uses `[0].src` to directly write into the `src` property for some reason (instead of using `attr()` as they should). – Pekka Mar 09 '12 at 16:26
  • 1
    @Pekka sure, but it's not a "convention" - there's nothing special about element 0. It's just how jQuery works! – Alnitak Mar 09 '12 at 16:28
  • @Pekka oh, and using `element.src` is actually better than using `$(element).attr(src, ...)`. – Alnitak Mar 09 '12 at 16:29
  • 1
    @ALnitak in this context, you're right of course, disregard what I said. But if you are explicitly working with a jQuery object, you generally want to use its setters and getters to comb over browser incompatibilities – Pekka Mar 09 '12 at 16:30
  • 1
    @Pekka right, I wouldn't bother to unwrap a jQuery object if I was going to re-use it (or chain another function call). – Alnitak Mar 09 '12 at 16:35

3 Answers3

3

Why $(this) is referring to a wrapped set instead of an individual element?

Because someone didn't know any better.

In this context if you want the original DOM element, just use this

On the other hand, if you wish to call jQuery methods on that element, use $(this).

Since all you're doing is setting a property of a DOM element, you should use the former:

template.find('.userPhoto img').error(function () { 
    this.src = '/images/default.png'; 
}).attr('src', image);
Alnitak
  • 334,560
  • 70
  • 407
  • 495
0

I think it's because so you can apply a method to a selection and have an unified api

$("a").each(function(){
  $(this).each(...).click(...);
});
$("a").click(...);
lcapra
  • 1,420
  • 16
  • 18
0

That's how jQuery works, it's the expected behavior.

$() turns DOM element(s) into a jQuery object (which pretends to be an array), which is a set of DOM element(s).

In your answer you don't need to use $().

Since, this is the element you want, you can just do:

template.find('.userPhoto img').error(function () { 
    this.src = '/images/default.png'; 
}).attr('src', image);

Or you can do this:

template.find('.userPhoto img').error(function () { 
    $(this).attr('src', '/images/default.png';);
}).attr('src', image);

$(this).attr('src' will change the attribute of all elements (in your case, one) in the set.

gen_Eric
  • 223,194
  • 41
  • 299
  • 337