了解常见的jQuery插件样板

时间:2018-03-11 21:58:09

标签: javascript jquery scope

我试图理解下面代码的第10行和第12行,并试图解释。如果适用,请纠正我。

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

第10行。如果提供给samplePlugin的参数是一个方法,那么使该方法与当前脚本的位置(即第10行)具有相同的this,并且......帮助! arguments在哪里定义? call()是什么?编辑。好吧,似乎Array.prototype.slice.call(arguments, 1)在除了第一个之外的所有参数中都有一个真正的数组,然而,仍然有点神秘。

第12行。否则,如果提供给samplePlugin的参数是一个对象或为空,那么使init方法与当前脚本的位置具有相同的this(即Line 12),......似乎更简单,但仍然需要帮助...

(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)
);

1 个答案:

答案 0 :(得分:3)

你自己解开了一些部分,但是涉及到JavaScript函数技巧的一个非常重要的部分。让我们把它们分开:

arguments是函数体内的“神奇”变量,它提供对函数参数的访问。它只是没有声明,并且像数组一样工作,但没有数组(稍后会变得很重要)。

如果要访问函数的第一个参数,可以查看arguments[0]。在您的特定函数中,它始终与变量method相同。

如果你想获得任何额外的参数(记住,你可以使用任意数量的参数调用JS函数,而不仅仅是声明的参数),第一遍可能如下所示:

arguments.slice(1)

但是,请记住,arguments不是数组,它只是一个。缺少所有Array方法。所以我们需要来自Array.prototype的{​​{3}},其中“真正的”数组来自:

Array.prototype.slice

要让slicearguments一起使用,必须使用arguments作为this进行调用:

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

borrow them

到目前为止一切顺利。

现在,假设jQuery插件被调用如下:

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

变量method现在是"method1"。第一个if被触发,因为 method1中的methods键,它是一个函数。因此,使用所有剩余的参数调用该函数:

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

第二个分支:如果像这样调用插件:

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

然后method == { foo: 'bar' }我们将在分支2中登陆,因为它是一个对象。样板作者的想法是,在这种情况下应该调用init方法:

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

methods['init']与JS中的methods.init相同。)我们不需要上面的拼接技巧,因为arguments[0] 不是任何方法名称