简体   繁体   中英

Understanding common jQuery plugin boilerplate

I am trying to understand lines 10 and 12 of the below code, and have given my attempt to explain. Please correct me as applicable.

//Line 10
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
//Line 12
return methods.init.apply(this, arguments);

Line 10. If the argument provided to samplePlugin is a method, then make that method have the same this as is at the current script's location (ie Line 10), and ... Help! Where is arguments defined? What is with the call() ? EDIT. Okay, it seems Array.prototype.slice.call(arguments, 1) makes a real array out of all the arguments except the first one, however, still is a bit of a mystery.

Line 12. Else if the argument provided to samplePlugin is an object or empty, then make the init method have the same this as is at the current script's location (ie Line 12), and ... Seems simpler, but still need help...

(function($){
    var methods = {
        init    : function (options) {return this.each(function () {/* ... */});},
        method1 : function ()        {return this.each(function () {/* ... */});},
        method2 : function ()        {return this.each(function () {/* ... */});}
    };

    $.fn.samplePlugin = function(method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));   //Line 10
        } else if (typeof method === 'object' || ! method) {
            return methods.init.apply(this, arguments);                                     //Line 12
        } else {
            $.error('Method ' +  method + ' does not exist on jQuery.samplePlugin');
        }    
    };
    }(jQuery)
);

You unraveled some parts yourself, but there's a non-trivial part of JavaScript function trickery involved. Let's put them apart:

arguments is a “magic” variable inside function bodies, that offers access to the function arguments. It's simply there without declaration, and works like an array but is no array (will become important in a moment).

If you want to access the first argument to a function, arguments[0] is the place to look. In your specific function, that's always identical to the variable method .

If you want to get any additional arguments (remember, that you can call JS functions with any number of arguments, not just the ones declared), a first pass might look like this:

arguments.slice(1)

but, remember, arguments is no array, it just looks like one. All Array methods are missing. So we need to borrow them from Array.prototype , where “real” arrays get them from:

Array.prototype.slice

To get slice to work with arguments , it must be called with arguments as this :

Array.prototype.slice.call(arguments, 1)

( Read up on Function.prototype.call )

So far so good.

Now, imagine the jQuery plugin gets called like this:

$('body').samplePlugin('method1', 'foo', 'bar');

The variable method is now "method1" . The first if is triggered, because there is a method1 key in methods , and it's a function. So the function is called with all remaining arguments:

methods['method1'].apply(this, ['foo', 'bar']);

Second branch: If the plugin is called like this:

$('body').samplePlugin({ foo: 'bar' });

then method == { foo: 'bar' } and we're landing in branch 2, since it's an object. The idea of the boilerplate author is, that in this case the init method should be called:

methods['init'].apply(this, arguments);

( methods['init'] is the same as methods.init in JS.) We do not need the splicing trick from above, since arguments[0] is not any method name.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM