开发者

who am I - JQuery, Plugin, $this, $(this), this, access to variable

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:

  1. It retrieves the bar property from the foo object.
  2. It calls the function that property references.
  3. It does #2 in such a way that this refers to foo.

(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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜