(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 );
我理解最终会发生什么的概念……但究竟是怎么回事?这部分让我感到困惑:
// Method calling logic if ( methods[method] ) { return methods[ method ].apply( this,arguments ); }
为什么Array.prototype.slide.call(argumetns,1)?变量“参数”从何而来?任何简短或更深入的解释都非常感谢.据说,这就是插件的编写方式……所以我想知道原因.
谢谢!
解决方法
arguments是JavaScript语言的一部分.当我第一次碰到它的时候,我很困惑.这不仅仅是你. :-)它是每个函数中的自动局部变量,并且是一个类似于数组的结构,为您提供所有参数(参见the spec第10.6节),例如:
function foo() { var index; for (index = 0; index < arguments.length; ++index) { alert(arguments[index]); } } foo("one","two"); // alerts "one",then alerts "two"
当我说参数是类似数组时,我的意思是它 – 它不是数组.它对参数的引用是实时的(和双向的).例如:
function foo(namedArg,anotherNamedArg) { alert(namedArg === arguments[0]); // alerts true,of course alert(anotherNamedArg === arguments[1]); // also alerts true namedArg = "foo"; alert(arguments[0]); // alerts "foo" arguments[0] = "bar"; alert(namedArg); // alerts "bar" }
请注意,在为namedArg分配值时,结果会反映在arguments [0]中,反之亦然.
参数非常酷,但只有在需要时才使用它 – 某些实现通过不挂钩来加速调用函数,直到/除非函数实际上首先尝试访问它,这会降低函数的速度(非常轻微).
function foo() { alert(foo === arguments.callee); // alerts true }
但是,出于几个原因,最好避免使用arguments.callee.一个原因是在许多实现中,它确实很慢(我不知道为什么,但是为了给你一个想法,如果你使用arguments.callee,函数调用开销可以增加一个数量级).另一个原因是你无法在ECMAScript5的新“严格”模式下使用它.
(有些实现也有arguments.caller – 不寒而栗 – 但幸运的是它从未普及过,并且在任何地方都没有标准化[也不可能].)
切片调用并应用
关于
return methods[ method ].apply( this,1 ));
正在做的是使用Array#slice方法将参数复制到数组中(减去第一个参数,即调用方法),然后将结果数组传递给它调用的函数实例上的Function#apply函数. Function#apply使用给定的this对象和作为数组提供的参数调用函数实例.代码不只是使用arguments.slice,因为(再次)参数实际上并不是一个数组,所以你不能依赖它拥有所有的数组函数,但是规范明确地说(在第15.4.4.10节中)你可以将Array.prototype.slice函数应用于类似数组的任何东西,这就是他们正在做的事情.
函数#application和函数#调用也是JavaScript的内置部分(参见第15.3.4.3节和第15.3.4.4节).以下是每个简单的例子:
// A function to test with function foo(msg,suffix) { alert(this.prefix + ": " + msg + suffix); } // Calling the function without any `this` value will default `this` // to the global object (`window` on web browsers) foo("Hi there","!"); // Probably alerts "undefined: Hi there!" because the // global object probably doesn't have a `prefix` property // An object to use as `this` var obj = { prefix: "Test" }; // Calling `foo` with `this` = `obj`,using `call` which accepts the arguments // to give `foo` as discrete arguments to `call` foo.call(obj,"Hi there","!"); // alerts "Test: Hi there!" // ^----^-----------^---- Three discrete args,the first is for `this`,// the rest are the args to give `foo` // Calling `foo` with `this` = `obj`,using `apply` which accepts the arguments // to give `foo` as an array foo.apply(obj,["Hi there","!"]); // alerts "Test: Hi there!" // ^---------------^---- Note that these are in an array,`apply` // takes exactly two args (`this` and the // args array to use)