5 ms·
But wouldn't multiple potentially long loops on initial load have a greater possible impact on user experience than one extra call to $() per event?
by xtian 16y ago
But wouldn't multiple potentially long loops on initial load have a greater possible impact on user experience than one extra call to $() per event?
- emehrkay 16y agoGreat point. I think that my simplistic example is just that, simplistic. A better solution for huge collections would be to memoize the retrieval of the $() obj with something like var memd = {}, getMem = function(obj){ var o; if(memd[obj]){ o = memd[obj]; }else{ o = memd[obj] = $(obj); } return o; }; and call that function instead of calling $() while inside of an event handler (I havent tested this code, but the concept is straight forward)
- arethuza 16y agoI don't want to appear snarky, but as you admit yourself ("I dont have any data on it") you don't know if creating a jQuery object is expensive or not (to be fair, I don't know either) - so why all the extra complexity if you don't know whether the thing you are trying to avoid (creating instance of jQuery during event handlers) actually causes problems or not?
- emehrkay 16y agoWell given that a lot of the "pro" jQuery tips say that one should avoid rerunning the selector in favor of some sort of memoization: $('.class').doSomehting(); $('.class').doSomethingElse(); $('.class').thirdThing(); in favor of var ele = $('.class'); ele.doSomething(); ele.doSomethingElse(); ele.thirdThing(); I would only assume that re-querying with the jQuery object inside of event handlers has the same adverse effects. Lets say you have a very simple tabbed thing //this is code that i've seen around var tabs = $('a.tab'), containers = $('div.container'); tabs.click(function(e){ var index = tabs.indexOf($(this)); tabs.removeClass('active'); $(this).addClass('active'); containers.css('display', 'none'); $(containers[index]).css('display', 'block'); }); vs //this is how id handle a simple tabber var tabs = $('a.tab'), containers = $('div.container'), all_containers = $.map(containers, function(i, c){ return $(c); }); $.each(all_tabs, function(i, tab){ var t = $(tab); t.bind('click', function(e){ tabs.removeClass('active'); t.addClass('active'); containers.css('display', 'none'); all_containers[i].css('display', 'block'); }); }); I just feel that the first one, while more concise (has it obvious areas of improvement, but general idea) would wind up being more expensive than the second. If running the jQuery object isnt too expensive, why is the practice of rerunning the same selector frowned upon?
- xtian 16y agoInteracting with the DOM is what's slow. It's especially slow if the native querySelectorAll method isn't available because any non-trivial selections necessitate iterating over the DOM tree. That's why you don't want to re-query a selection multiple times. That's also why it's recommended that all selections start with an id. The size of the tree to iterate over can be quickly reduced using the native getElementByID method. In the case of $(this), the DOM node is already passed to the event handler, so wrapping it in a jQuery object doesn't touch the DOM tree at all. Furthermore, I always cache it (var $this = $(this);) if I'm going to use it more than once. Also, in your first example, you don't have to rewrap containers[index] in a jQuery object. All the elements in the selection are already wrapped.
- emehrkay 16y ago> Also, in your first example, you don't have to rewrap containers[index] in a jQuery object. All the elements in the selection are already wrapped. Really? I think that is the whole point of this long comment thread -- that the elements in a collection arent already wrapped. http://jsfiddle.net/8nqtA/ http://jsfiddle.net/8nqtA/ This doesnt work unless i wrap a[i] in $() But like you're saying, it may be fruitless since the dom is the bottleneck and we're bypassing it by already having the element.
- M1573RMU74710N 16y agoWell there's a few problems with that example: 1) You've got a "global" named a and then a local variable (via the argument) inside the each function called "a"...so that really confuses things. 2) a[i] where a is a jQuery object returns an unwrapped DOM element...what you want is .index(). 3) What you're doing is sort of roundabout... Why not: var d = $('div'), a = $('a'); a.each(function(i, el){ d.text(d.text() +' '+ $(this).text() ); }); Or if you really want to do it your way: var d = $('div'), a = $('a'); a.each(function(i, el){ d.text(d.text() +' '+ a.index(i).text() ); });
- 16y ago