What is "context" in jQuery selector?

JavascriptJqueryJquery Selectors

Javascript Problem Overview


Is there any difference between

$('input.current_title', '#storePreferences').prop('disabled', false);

and

$('#storePreferences input.current_title').prop('disabled', false);

?

Javascript Solutions


Solution 1 - Javascript

There IS a difference, and it is NOT subtle as others believe.

EDIT: Layman's example of each:

  • Call all the blue houses in town (context), if Jane is there, tip off her hat.
  • Call all the buildings in town (no context yet). IF it is a blue house (add context) and Jane is there, tip off her hat.

Let's break down what it selects.

First we have: Context selector http://api.jquery.com/jQuery/#jQuery-selector-context

$('input.current_title', '#storePreferences').prop('disabled', false);

This says: use a selector in context. http://api.jquery.com/jQuery/#jQuery-selector-context

While this form MIGHT work, it should really be:

$('input.current_title', $('#storePreferences')).prop('disabled', false);

OR

var myContext = $('#storePreferences');
$('input.current_title', myContext).prop('disabled', false);

This meets the requirement for a context selector being met: "A DOM Element, Document, or jQuery to use as context".

This says: using the context, find inside that the selector. An equivalent would be:

$('#storePreferences').find('input.current_title').prop('disabled', false);

Which is what happens internally. Find '#storePreferences' and in that find all the 'input.current_title' matching elements.


Then we have: Descendant Selector

$('#storePreferences input.current_title').prop('disabled', false);

This is a Descendant Selector (“ancestor descendant”) http://api.jquery.com/descendant-selector/ which says: find all the input.current_title elements inside the #storePreferences element. THIS IS WHERE IT GETS TRICKY! - that is EXACTLY what it does -

finds ALL the input.current_title (anywhere), then finds those INSIDE the #storePreferences element.

Thus, we run into jQuerys' Sizzle right to left selector - so it initially finds MORE(potentially) than it needs which could be a performance hit/issue.

Thus the form of:

$('#storePreferences').find('input.current_title').prop('disabled', false);

would perform better than the Descendant version most likely.

Solution 2 - Javascript

> Is there any difference between $('input.current_title', '#storePreferences').prop('disabled', false); and $('#storePreferences input.current_title').prop('disabled', false);?

Yes, but it's subtle

The difference is in how the elements are selected.

$('input.current_title', '#storePreferences');

is equivalent to1:

$('#storePreferences').find('input.current_title');

but is not equivalent to:

$('#storePreferences input.current_title');

even though the same elements will be affected.

The reason they're not the same is that using find allows for the context to be returned to #storePreferences when end is called.

1: lines 194-202 in the jQuery v1.9.1 source
// HANDLE: $(expr, $(...))
} else if ( !context || context.jquery ) {
    return ( context || rootjQuery ).find( selector );

// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
    return this.constructor( context ).find( selector );
}

in the context of your question, the same elements will be modified, so there is no difference in functionality, but it's important to be aware of the broader implications of the selectors you use.

Solution 3 - Javascript

In your example I believe that there is little difference.

It comes into better use when you start selecting multiple elements in a specific DOM element.

// Get the div in the body with the id of storePreferences
var sp = $('body div#storePreferences');


// jQquery will only look for **input.current_title** **input.name** **input.age** in side **sp** div in the DOM.
// Faster
$('input.current_title', sp).prop('disabled', false);
$('input.name', sp).prop('disabled', false);
$('input.age', sp).prop('disabled', false);




// jQquery will look for **input.current_title** in entire DOM
// Slower
$('#storePreferences input.current_title').prop('disabled', false);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDimsView Question on Stackoverflow
Solution 1 - JavascriptMark SchultheissView Answer on Stackoverflow
Solution 2 - JavascriptzzzzBovView Answer on Stackoverflow
Solution 3 - JavascriptHello-WorldView Answer on Stackoverflow