Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I pass a jQuery or DOM object as arguments? (Performance Question)

Which is better performance wise.

foo(this);

function foo(element) {

    $(element).index();

}

Or should I do

foo($(this));

function foo($element) {

    $element.index();

}

Obviously taking into account that I will be using the argument a fair few times inside the function.

Thanks! Connor

like image 795
Connor Burton Avatar asked Sep 24 '11 13:09

Connor Burton


3 Answers

It doesn't matter where you wrap an object on jQuery if you're going to wrap it anyway.

It only matters that you cache the wrapping result and don't wrap it twice.

For that matter the following rules apply to many plugins' code:

1) jQuery vars are all prefixed with $: var $this = $(this)

2) never wrap $-prefixed var in $

3) always cache (save to var) any jQuery-wrapped expression used more than once

4) if the same wrapped object (like var $items = $('ul li');) occurs more than once in several similar functions, move it to the outer scope and rely on closure.

like image 108
Guard Avatar answered Oct 19 '22 23:10

Guard


If you're writing a function that's going to take one jQuery object as a parameter, you really should consider writing it as a jQuery plugin instead.

jQuery.fn.yourFunction = function(otherArg1, otherArg2, ...) {
  // ...
};

Then instead of writing

yourFunction($(whatever));

you can write

$(whatever).yourFunction().someOtherJQueryFunction();

Inside the function, the this value will be the jQuery object itself. A pattern to use for most common DOM-related functions is:

jQuery.fn.yourFunction = function(otherArg1, otherArg2, ...) {
  return this.each(function() {
    var $element = $(this);
    // do stuff ...
  });
};

Note that in the outer level of the function, this is not wrapped as $(this) because it's already guaranteed to be a jQuery object. That is not the case in the body of an "each()" function, or anything else like that.

like image 26
Pointy Avatar answered Oct 19 '22 23:10

Pointy


If you intend to only pass a single element to the function, then it doesn't really matter. I would design the function parameter depending upon what I was likely to already have handy at the time of calling. If I never had it in a jQuery object already at the time of calling, then I would just pass a DOM element and let the function make it into a jQuery object (if needed). If I always already had it in a jQuery object, then it will perform better to pass that object that I already have rather than extra the DOM element, then make it into another jQuery object inside the function.

If you intend to pass multiple elements to the function, then it's probably easier to just pass a jQuery object because it's a nice convenient wrapper for the multiple objects.

As Pointy said, the most elegant solution is to make your function a plugin and then it will automatically accept lots of different arguments including a selector, a DOM element, a DOM element array or a jQuery object (all handled for you by the jQuery infrastructure).

You will achieve the best performance if you only make the DOM element into a jQuery object once. Passing a DOM or passing a jQuery object as the argument will have the same performance (both are passing a reference to an object). The plug-in idea will actually have slightly worse performance because it is so general purpose and accepts lots of different arguments and thus it has to identify what type of argument was passed. That performance difference is perhaps not noticeable compared to the time that the .index() method takes itself.

like image 42
jfriend00 Avatar answered Oct 20 '22 00:10

jfriend00