关于jQueryPlugin开发的官方框架的理解
Liber 2012-10-10 10:55

上代码:

(function( $ ){
 
  var methods = {
    init : function( options ) { 
      // THIS 
    },
    show : function( ) {
      // IS
    },
    hide : function( ) { 
      // GOOD
    },
    update : function( content ) { 
      // !!! 
    }
  };
 
  $.fn.tooltip = function( method ) {
     
    // Method calling logic
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }    
   
  };
 
})( jQuery );
 
});
 
// calls the init method
$('div').tooltip(); 
 
// calls the init method
$('div').tooltip({
  foo : 'bar'
});
 
// calls the hide method
$('div').tooltip('hide'); 
 
// calls the update method
$('div').tooltip('update', 'This is the new tooltip content!'); 

以上代码是官方jQuery Plugins开发提供的开发文档上的一个例子。(参见:http://docs.jquery.com/Plugins/Authoring

这里主要是对第22行代码的理解: return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));

首先是Array.prototype.slice.call( arguments, 1)这个方法,前面这一段实际上只是单纯的对slice方法的调用,然后通过call设置其执行时的作用域。我们知道Array是JS默认的引用类型,也是一个内置对象,而每个引用类型都有一个prototype属性,实际上prototype才是保存它们所有实例方法的真正所在。(有人可能会疑问,为什么访问实例化之后的对象的prototype里面的方法的时候不能加.prototype,而这里访问Array这种内置对象的prototype下面的方法的时候要加.prototype。好吧,先记住这个规则,具体的原因可以参看《JavaScript高级程序设计(第三版)》第148页的解释) call方法接收两个参数,第一个参数是一个对象arguments,即设置其执行时的作用域为arguments对象;第二个参数1实际上是要传给slice方法的参数,我们知道slice方法是从位置0开始检索的,而我们调用插件的时候,如:$(‘div’).tooltip(‘update’, ‘This is the new tooltip content!’); 实际上第一个参数是我们想要执行的方法名,第二个参数才是我们想要传入的参数。slice执行之后,返回一个数组,正好作为apply的第二个参数传过去。

举例来说,当插件的调用方式是:
1. $(‘div’).tooltip();
第22行代码不会执行,因为if()里面的判断条件为false;

  1. $(‘div’).tooltip(‘hide’);
    第22行代码实际上就是:
    return methods[‘hide’].apply( this, [] );
    methods[ method ]实际上是访问对象属性的另一种形式,换成一种我们熟悉的形式就好理解了:
    return methods.hide.apply( this, [] );

  2. $(‘div’).tooltip(‘update’, ‘This is the new tooltip content!’);
    第22行代码实际上就是:
    return methods.update.apply( this, [‘This is the new tooltip content!’] );