12

Given the following HTML example...

<div id='div1'>div one</div>
<div id='div2'>div two</div>

...I found that the following jQuery code...

$('#div1').click(function() {

    var $d = $(this);    // Using 'this' instead of '#div1'

    $d.add('#div2').remove();
});

...would not add #div2 to the set referenced by $d, but this code...

$('#div1').click(function() {

    var $d = $('#div1');    // Using '#div1' instead of 'this'

    $d.add('#div2').remove();
});

...successfully added #div2.

Upon consulting firebug, I found that using $(this) gave the jQuery object a context of #div1, but doing $('#div1') gave the object a context of document.

Given this information I tried...

var $d = $(this, document);

...and the add() function worked as expected.

So here's the question. Could someone please explain to my why a different context is assigned when using $(this) vs $('#div1')?

0

1 Answer 1

11
+500

Edited to better address your question:
First, look at the relevant code here, this is how jQuery handles the $() call. When you're passing a DOM element (which this is, it's the div itself) the context is the DOM element itself, this better allows handling of document fragments, etc. When you pass a string, the default context is document (because it's the top ancestor to search from). Remember a $(selector, context) is actually calling context.find(selector) under the covers, so it makes sense to start at document if nothing's specified.

Note: you can always check the context, it's an available property, like this: $(this).context

For the .add() behavior:
.add() uses the same context for selecting as the jQuery element you're adding to, so what you're seeing is the expected behavior. For a better description, see how .add() is written:

add: function( selector, context ) {
    var set = typeof selector === "string" ?
                jQuery( selector, context || this.context ) :
                jQuery.makeArray( selector ),
                all = jQuery.merge( this.get(), set );

    return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
            all :
            jQuery.unique( all ) );
    }

Note how it uses the current context if none is passed. To override this though, it accepts a context, to which you can pass document and get the result you want, like this:

$('#div1').click(function() {
   $(this).add('#div2', document).remove();
});
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the answer. I think maybe I'm just not understanding the purpose/use of the context of a jQuery object. Why does $d have a context of #div1 in the first place instead of document?
@patrick - You can see how $(this) is handled here: github.com/jquery/jquery/blob/master/src/core.js#L59 When you do $(DOMElement) the context is that DOM element, just how it works. For example, you could be dealing with an element that's not in the DOM, in a document fragment for example, so document doesn't always work.
@patrick - I re-read your post and re-wrote most of the answer to better address your main question, hopefully that clarifies it a bit more, let me know if it still leaves questions.
OK, I think I'm getting it. So the reason jQuery assigns #div1 is that jQuery doesn't really know what the heck else to put there (without doing a traversal every time, I suppose). So overriding the context in $d is safe and irrelevant in terms of expected functionality.

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.