I have a problem with identify the object that runs the function
<div id="test1">lorem</div>
<div id="test2">ipsum</div>
<script type="text/javascript">
$(document).ready(function() {
$('#test1').plugin(); //alert: I am test1
$('#test2').plugin(); //alert: I am test2
$('#test1').plugin.fun(); //alert: I am undefined and I am undefined
$('#开发者_JAVA百科test2').plugin.fun(); //alert: I am undefined and I am undefined
});
(function($) {
$.fn.plugin = function() {
$this = $(this);
alert('I am '+$(this).attr('id'));//<-- it works
}
$.fn.plugin.fun = function() {
alert('I am '+$(this).attr('id')); //<-- doesn't work!
alert('and I am '+$this.attr('id')); //<-- also doesn't work!
}
})(jQuery);
</script>
To understand what $('#test1').plugin.fun();
is doing, we have to look at how this
is set within JavaScript functions. We'll start with theory, then come back to your plug-in.
In JavaScript, this
is defined entirely by how a function is called. The most common way is to set it as a by-product of calling the function from an object property:
var foo = {
msg: "I'm foo!",
bar: function() {
alert(this.msg);
}
};
foo.bar(); // alerts "I'm foo!"
That line foo.bar();
does three distinct things:
- It retrieves the
bar
property from thefoo
object. - It calls the function that property references.
- It does #2 in such a way that
this
refers tofoo
.
(More here: Mythical Methods.)
So in the call
$('#test1').plugin.fun();
...this
within fun
will be plugin
, because we're calling fun
via a property on plugin
.
You might consider using the mechanims used by jQuery UI, which is to have "methods" of the plug-in accessible via a main function, with the names as strings. For instance, on a jQuery UI Draggable
instance, you can call methods like this:
$('#test1').draggable('disable');
See their Draggable
documentation for more examples, but basically your calls would look like this:
$('#test1').plugin('fun');
More about function calls:
There's another way to set this
when calling a function: Through the call
and apply
functions on the function instance:
var f = function() {
alert(this.msg);
};
var foo = {
msg: "I'm foo!"
};
f.call(foo); // alerts "I'm foo!"
f.apply(foo); // alerts "I'm foo!" too
call
and apply
call a function, setting the this
value to the first argument you pass into them. The difference between call
and apply
is how you pass arguments to the target function. With call
, you just add further arguments to the call
function; with apply
, you give an array of arguments as the second argument to apply
. Examples:
function f(arg1, arg2) {
alert(this.msg + " (" + arg1 + ", " + arg2 + ")");
}
var foo = {
msg: "I'm foo!";
};
f.call(foo, "one", "two"); // Alerts "I'm foo! (one, two)"
// ^-- "one" and "two" are discrete arguments
f.apply(foo, ["one", "two"]); // Alerts the same thing
// ^------------^-- "one" and "two" are in an array
The fun
function doesn't have any direct relation to the object that you are using in the call, so this
will just be the window
object.
When you are using $('#test1').plugin
, you get a reference to that function, and from that you access the function fun
, but what you get is simply a regular function. You could just as well use $.fn.plugin.fun
to get to the function, the use of the jQuery object with the selector has no relevance at all once you have got the reference to the fun
function.
The jQuery object will actually be discarded before the fun
function is called, so it's impossible to reach it from the function.
精彩评论