Reputation: 19664
I was reading the jQuery documentation for plugin development and I ran across a line of code I cannot wrap my head around.
$.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' );
}
The line in question:
return methods[method].apply(this, Array.prototype.slice.call(arguments,1));
I understand that all javascript objects inherit call() and apply() and I understand the differance between these two functions. What I don't understand is the prototype on the Array. Array objects already have a slice() so why is the prototype needed here? Since call() takes two arguments which are a 'this' (context) and a list of arguments I don't understand how the above call invocation works. Can someone help me understand this line?
Thanks
Upvotes: -1
Views: 94
Reputation: 154838
Very simply speaking, the function Array.prototype.slice
is as follows:
Array.prototype.slice = function(from) {
return elements of `this` from index `from`;
};
so when you do Array.prototype.slice.call(obj, a)
, you'll get obj
with elements only from index a
.
The problem is that it is only available on arrays, but you can get it working on objects as well using the syntax you described:
var obj = { length: 3, 0: 'a', 1: 'b', 2: 'c' };
Array.prototype.slice.call(obj, 1); // { length: 2, 0: 'b', 1: 'c' }
The same goes for arguments - it isn't an array so you have to access the function with Array.prototype.slice.call
.
Basically, the only thing that arrays are different from arguments is that arrays inherit from Array.prototype
, so that you can can call arr.slice()
directly.
Upvotes: 1
Reputation: 349002
The arguments
object inherits from Object.prototype
. It may look like an array, but it isn't. To perform array operations on it, the following line is necessary:
Array.prototype.slice.call(arguments,1)
The previous line copies the arguments
"array", and uses the slice(1)
method on it.
Array.prototype.slice(arguments, 1)
is equivalent to:
arguments
to a true array (by setting this
of Array.slice` to arguments).slice(1)
method to return an array which does not contain the first element.(Note that the arguments
object is not modified during this process)
Pseudo-code:
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"]
Upvotes: 1