我正在阅读jQuery's "Plugins/Authoring"虽然我已经写了一些jQuery-Plugins。现在我看到jQuery有一种特殊的方法来确定方法和调用:
(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, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
}
为什么Array.prototype.slide.call(argumetns, 1)
?变量“参数”从何而来?任何简短或更深入的解释都非常感谢。据说,这就是应该编写插件的方式......所以我想知道原因。
谢谢!
答案 0 :(得分:15)
arguments
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"
当我说arguments
类似于数组时,我的意思是 - 它是不是数组。它对参数的引用是 live (和双向)。例如:
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]
中,反之亦然。
arguments
真的很酷,但只在你需要时才使用它 - 某些实现通过不挂钩来加速调用函数,直到/除非函数实际上首先尝试访问它,这会降低函数的速度(非常轻微)。
arguments
也有一个名为callee
的属性,它是对函数本身的引用:
function foo() {
alert(foo === arguments.callee); // alerts true
}
但是,出于多种原因,最好避免使用arguments.callee
。一个原因是在许多实现中,它真的慢(我不知道为什么,但是为了给你一个想法,函数调用开销可以增加一个数量级如果您使用arguments.callee
)。另一个原因是你无法在ECMAScript5的新“严格”模式下使用它。
(有些实现也有arguments.caller
- 颤抖 - 但幸运的是它从未普及过,并且在任何地方都没有标准化[也可能不会]。)
slice
来电和apply
关于
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
正在做的是使用Array#slice
方法将参数复制到数组中(减去第一个参数,这是要调用的方法),然后将结果数组传递给Function#apply
函数在它正在调用的函数实例上。 Function#apply
使用给定的this
对象调用函数实例,并将参数作为数组提供。代码不只是使用arguments.slice
,因为(再次)arguments
实际上并不是一个数组,因此您不能依赖它具有所有数组函数,但规范明确指出(在第15.4节中) .4.10)你可以将Array.prototype.slice
函数应用于任何类似数组的函数,这就是他们正在做的事情。
Function#apply
和Function#call
也是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)
答案 1 :(得分:3)
arguments
是一个关键字,传递给函数的参数。但是你不想要所有,因为你知道的第一个<{1}},所以这是在.apply()
中使用的每个参数超过第一个参数...将这些参数传递给第一个method
参数中指定的方法。
如果找不到method
(意思是第一个参数不是method
,'init'
,'show'
或'hide'
,那么它就会出现到'update'
部分,并将所有参数传递给else
方法(默认情况下,如果你愿意)。
例如:
init
会调用.tooltip({ thing: value })
,因为这是默认init({ thing: value })
会致电.tooltip('show', var1, var2)
答案 2 :(得分:1)
变量arguments
是javascript变量的定义。它存储在函数中调用的所有参数。例如:
function variablesCount() {
alert(arguments.length);
}
variablesCount(var1, var2); // alerts 2
答案 3 :(得分:1)
Array.prototype.slide.call(argumetns, 1)
将arguments
伪数组转换为实数数组(跳过第一个元素)。
arguments
包含您当前所使用的函数的所有参数。它由JavaScript自动提供。由于我们需要一个真正的数组(arguments
无法操纵等),我们使用此语句将其转换为一个。
答案 4 :(得分:1)
arguments
是一个特殊的JavaScript变量,意思是“赋予此函数的所有参数”。它不是一个数组,但行为几乎就像一个数组,所以它不是说arguments.slice(1)
而是调用Array.prototype.slice.call(arguments, 1)
;除了列表中的第一个值之外,它正在做什么 - 对于func(1, 2, 3, 4)
它将是[2, 3, 4]
。
最终结果是,当您致电$.fn.tooltip('foo', 'bar', 'baz')
时,它会尝试拨打methods['foo']('bar', 'baz')
。