Forum Moderators: open

Message Too Old, No Replies

is jQuery.fn.whatever better than function whatever()

         

csdude55

7:41 am on Jun 7, 2017 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I'm already loading jQuery, so this isn't a question of whether I should use jQuery JUST for this. This is really just for my own education.

As far as I can tell, these two are basically the same:

// Usage:
// $('foo').whatever('bar');
jQuery.fn.whatever = function(y) {
alert(this); // foo
alert(y); // bar
}


// Usage:
// whatever('foo', 'bar');
function whatever(x, y) {
alert(x); // foo
alert(y); // bar
}


I understand that using jQuery.fn is an alias to jQuery.prototype, but I really don't understand what that means. Is there an advantage (speed, reliability, compatibility, etc) to use one format over the other?

Fotiman

2:13 pm on Jun 7, 2017 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Your comparison is slightly off. In your first example, *this* is the jQuery object (represented by 'foo'). In your second example, *x* is the string 'foo'. The first approach is essentially how you create a jQuery Plugin.

If you want a method that you can call on a jQuery selection (to perform operations on the selection), that's when you'd probably want to go with the first approach. For example:

// Replace text contents with 'whatever... ' plus the string passed in
jQuery.fn.whatever = function (y) {
this.text('whatever... ' + y);
return this;
}


So I could do something like:

$('p').whatever('no soup for you!');

And that would replace the text of my p elements with 'whatever... no soup for you!'

If I wanted to create a standalone method to do that, it would mean I'd have to manage the DOM iteration myself. I could still use jQuery for this:

function whatever(x, y) {
$(x).text('whatever...' + y);
}

The down side to this is that now I've added a jQuery dependency within my function (making it harder to unit test).

If you want to perform your own custom work on jQuery selections and it's generic enough that you might perform it multiple times from different places within the code, then that's when you might consider a plugin. In the end, they're both function calls, and performance should be similar. The advantage to the plugin approach is that when this function is called, the DOM selection work has already been performed, meaning this is a smaller, more specific chunk of code that can perform a single task. You need to perform the DOM selection one way or another, so there's no real time saving, but the difference is that your method either does that lookup AND does it's task, or it just does it's task using the lookup that was done separately.

csdude55

1:19 am on Jun 8, 2017 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Just for the sake of clarity, would that this be $(this)? If not, what's the difference? I'm playing with the code, and in some cases using this isn't working (no console error, though) and I'm not sure why.

Fotiman

2:40 am on Jun 8, 2017 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



In my example, _this_ is the jQuery object, so you wouldn't need to do $(this). Got any example code you can share? You could also use browser developer tools to add breakpoints and inspect the values at runtime to see what's going on. Chrome has the best tools IMO, but you should be able to debug with any browser.

csdude55

5:48 am on Jun 8, 2017 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I think I figured it out. Within the jQuery.fn.whatever I could use this, but within a function I had to use $(this).

But I don't understand exactly why. In researching I've found that this is the same as $(this)[0], so it can be used in situations where only one element is returned. But then in this:

$('#body_con').on('swipeleft', function() {
$(this).css('left', '0');
});

It appears to me that only one element is returned, but this.css didn't work, I had to change to $(this). But shouldn't $(this)[0], and thereby this, be equivalent to #body_con?

Fotiman

1:53 pm on Jun 8, 2017 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I think I figured it out. Within the jQuery.fn.whatever I could use this, but within a function I had to use $(this).

Correct. When you create a jQuery plugin method (jQuery.fn.whatever), the scope of this within that method will be a jQuery object. If you use a regular function, depending on how you call the method, this might be the DOM element instead. So that's why you would need to wrap that with $(), so you get a jQuery object that's representing that DOM element.

$('#body_con')

That will return a jQuery object, which contains a single DOM element that has an id of body_con. The "on" method of jQuery takes in the event name, and the handler function (it can take other optional parameters, but lets ignore them for this example). Within the "on" method itself (as defined in the jQuery source code), this would be the jQuery object, but remember, the on method takes in this handler, and it changes the scope for the handler so that this is a reference to the element instead of the jQuery object. Therefore:
$('#body_con').on('swipeleft', function() {
// this == the element, not the jQuery object representing the element
// so to call jQuery method "css" on the element, need to wrap in jQuery object first
$(this).css('left', '0');
});