我正在阅读用于插件开发的 jQuery 文档,并且遇到了一行我无法理解的代码。
$.fn.tooltip = function( method ) {
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' );
}
有问题的行:
return methods[method].apply(this, Array.prototype.slice.call(arguments,1));
我了解所有 javascript 对象都继承 call() 和 apply() 并且我了解这两个函数之间的区别。我不明白的是数组上的原型。数组对象已经有一个 slice() 那么为什么这里需要原型呢?由于 call() 采用两个参数,即“this”(上下文)和参数列表,我不明白上述调用调用是如何工作的。有人可以帮我理解这句话吗?
谢谢
arguments
对象继承自Object.prototype
。它可能看起来像一个数组,但事实并非如此。要对其执行数组操作,需要以下行:
Array.prototype.slice.call(arguments,1)
上一行复制
arguments
“数组”,并对其使用 slice(1)
方法。
Array.prototype.slice(arguments, 1)
相当于:
arguments
转换为真正的数组(通过将 Array.slice` 的 this
设置为参数).slice(1)
方法返回不包含第一个元素的数组。(注意,在此过程中
arguments
对象没有被修改)
伪代码:
var arguments = {1: "arg1", 2: "arg2", 3: "arg3", length: 3};
var copy = convert_object_to_array(arguments); //This function does not exists
// copy looks like: ["arg1", "arg2", "arg3"]
copy.slice(1); //Returns ["arg2", "arg3"]
很简单的来说,函数
Array.prototype.slice
如下:
Array.prototype.slice = function(from) {
return elements of `this` from index `from`;
};
因此,当您执行
Array.prototype.slice.call(obj, a)
时,您将得到 obj
,其中元素仅来自索引 a
。
问题是它仅适用于数组,但您也可以使用您描述的语法使其适用于对象:
var obj = { length: 3, 0: 'a', 1: 'b', 2: 'c' };
Array.prototype.slice.call(obj, 1); // { length: 2, 0: 'b', 1: 'c' }
参数也是如此 - 它不是数组,因此您必须使用
Array.prototype.slice.call
访问该函数。
基本上,数组与参数的唯一不同之处在于数组继承自
Array.prototype
,因此您可以直接调用arr.slice()
。