Nick
Nick

Reputation: 19664

jQuery Plugin Architecture Syntax - What does this line mean?

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

Answers (2)

pimvdb
pimvdb

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

Rob W
Rob W

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:

  • Convert arguments to a true array (by setting this of Array.slice` to arguments)
  • Use the .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

Related Questions