5

Today I was making an effect for share-icons using jQuery. The effect is a bit complicated so I tried to think of a way to optimize preformance. I ended up caching the $(this) object into array.

Effect Demo

I uploaded a working example of the effect using the array-cached objects (Hover on the icons to see the effect): http://mahersalam.co.cc/addthis/

HTML:

<div id="share-widget" class="addthis_toolbox">
    <a class="addthis_button_favorites" title="أضف للمفضلة"><div>أضف للمفضلة</div></a>
    <a class="addthis_button_facebook" title="شارك في فيسبوك"><div>شارك في فيسبوك</div></a>
    <a class="addthis_button_twitter" title="شارك في تويتر"><div>شارك في تويتر</div></a>
    <a class="addthis_button_email" title="أرسل الصفحة بالإيميل"><div>أرسل الصفحة بالإيميل</div></a>
    <a class="addthis_button_compact" title="أضغط هنا لمشاهدة المزيد من خدمات المشاركة"><div>المزيد من الخدمات</div></a>
</div>

Javascript:

// Return jQuery-obj of the share links
var shareLinks = $('#share-widget').find('a').css('opacity', 0.8);

//////////////////////////////////////////
// Only jQuery way
//////////////////////////////////////////

shareLinks.hover( 
    function () {
        $(this).clearQueue()
            .siblings()
                .stop(true,false).fadeTo('fast', 0.3)
            .end()
                .stop(true, true).fadeTo('normal', 1);
    },
    function () {
        shareLinks.delay(100).fadeTo('normal', 0.8);
})


//////////////////////////////////////////
// jQuery + Array cache way
////////////////////////////////////////// 

// Cache the array
var linksArr = [];

$.each( shareLinks, function (i) {

    linksArr.push( $(this) );

    linksArr[i].hover( function () {
        linksArr[i].clearQueue()
                    .siblings()
                        .stop(true,false).fadeTo('fast', 0.3)
                    .end()
                        .stop(true, true).fadeTo('normal', 1);
     },
    function () {
        shareLinks.delay(100).fadeTo('normal', 0.8);
    })
});

I just want to know if the array cached objects will make the performance faster or is it just not necessary. Also if anyone have a better idea to make this effect, I'm all ears ^^.

1

3 Answers 3

4

In this case it is not necessary. It is even more difficult to understand imo and maybe even slower. In your code:

shareLinks.hover( 
    function () {
        $(this).clearQueue()
            .siblings()
                .stop(true,false).fadeTo('fast', 0.3)
            .end()
                .stop(true, true).fadeTo('normal', 1);
    },
    function () {
        shareLinks.delay(100).fadeTo('normal', 0.8);
});

you are accessing $(this) only once anyway, why do you want to cache it? Afaik, $(this) is cheap anyway as it does not cause a search in the DOM.


It is only of advantage if you are evaluating the same selector several times (e.g. in a loop):

for(...) { 
   $('#share-widget div ul li > a').something(i);
}

is better written as

var $elements = $('#share-widget div ul li > a');
for(...) { 
   $elements.something(i);
}

Update:

Regarding what happens if you call $(this), this is the corresponding part from the code:

// Handle $(DOMElement)
if ( selector.nodeType ) {
    this.context = this[0] = selector;
    this.length = 1;
     return this;
}

and this is almost the at the top of the function. So it is really not doing much.

Sign up to request clarification or add additional context in comments.

4 Comments

shareLinks is a collection of jQ-objs. So $(this) will change for every object. I don't understand why I should make a new jQ-obj when it's already inside shareLinks. That's why I added them to an array.
@Maher4Ever: But this is not a speed issue, because creating a jQuery object from $(this) is cheap. This would be more of a memory concern. And besides that, this is passed directly in the functions scope, whereas linksArr has to be looked up on runtime (ok thi argument is a bit weak because $ has to be looked up too) and you have an additional array access. Most of the time you don't need to cache $(this) because creating it is cheap.
I thought that $(this) was expensive! It's really a good info to know, thank you.
@Maher4Ever: I mean you should avoid unnecessary calls to $() but in your case calling $(this) is absolutely normal.
1

The only caching I see going on is when you use this line

var shareLinks = $('#share-widget').find('a').css('opacity', 0.8);

which could perhaps be made faster by combining the (but I doubt it, and it's a single selector, so not that much to worry about here)

var shareLinks = $('#share-widget a').css('opacity', 0.8);

Everything else I see isn't really caching. Ergo I'm gonna put in my $0.05 and tell you to make it readable first and foremost, because readable code is maintainable code. Everything else is fluff for your ego.

Comments

1

One way to improve performance, especially if you have a lot of links, is to use JQuery's .delegate() function:

$('#share-widget').delegate('a', 'mouseenter', function() {
    $(this).clearQueue()
        .siblings()
            .stop(true,false)
            .fadeTo('fast', 0.3)
        .end()
            .stop(true, true)
            .fadeTo('normal', 1);
});
$('#share-widget').delegate('a', 'mouseleave', function() {
    shareLinks.delay(100)
        .fadeTo('normal', 0.8);
});

Comments

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.