Reputation: 20093
Given the example below (click "content" on the right if you're using the jsfiddle link), why does self
fall out of scope when it reaches the clickHelper()
?
I can think of two ways to fix it... (1) I can pass it in as an argument, or (2) I can define var self;
inside of the plugin (above function clickHelper()
).
I don't want to do #1 though, because in my real implementation, I have a bunch of arguments already and a bunch of helper functions... I was hoping to use scope to avoid passing self
around everywhere.
And I don't want to use #2 because it seems like if this plugin was used for multiple elements on the page, there could be race conditions... my assumption is that jQuery has 1 instance of the plugin, and therefore var self
would only exist once.
I'm basically looking for the best practice of keeping this
in scope inside of click event raised for a jQuery plugin.
<div id="a1">
content
</div>
<script type="text/javascript">=
function info(n, s) {
var id = (typeof (s.id) == "undefined") ? '' : ': ' + s.id;
alert(n + ': ' + s + ': ' + typeof (s) + id);
}
(function ($) {
$.fn.myPlugin = function () {
function clickHelper() {
info('self in the Helper...', self);
self.innerHTML += '2';
}
function clickHandler() {
var self = this;
info('self in the Handler', self);
self.innerHTML += '1';
clickHelper();
}
this.bind('click', clickHandler);
};
}(jQuery));
$(function () {
$('#a1').myPlugin();
});
</script>
ETA: #1 is probably the best bet if you don't mind the extra arguments, because #2 does race condition/thread safe issues as demonstrated here (click content 1, ok, and then content 2 really quick). You can get away with #2 by defining your helper methods inside your handler method as demonstrated here, which might work well for your if all your helper methods do is support your handler method. And #3, I suppose, instead of calling JavaScript functions like you normally would clickHelper()
, just use a proper closure function(this) { var self = this; clickHelper() };
.
Upvotes: 0
Views: 734
Reputation: 35319
Variables are only available to the functions in which they are created. So by creating self
inside of clickHelper
you are making it a local variable only to the clickHelpers
function.
By moving it into myPlugins
scope its now accessible to the nested functions.
$.fn.myPlugin = function () {
var self = {}; // self declared here instead can be used within this scope now
function clickHelper() {
info('self in the Helper...', self);
self.innerHTML += '2';
}
function clickHandler() {
self = this;
info('self in the Handler', self);
self.innerHTML += '1';
clickHelper();
}
this.bind('click', clickHandler);
};
Upvotes: 1