views:

3554

answers:

6

I am going through John Resig's excellent Advanced javascript tutorial and I do not thoroughly understand what's the difference between the following calls: (please note that 'arguments' is a builtin javascript word and is not exactly an array hence the hacking with the Array.slice instead of simply calling arguments.slice)

>>> arguments  
[3, 1, 2, 3]  
>>> Array.slice.call( arguments )  
3,1,2,3 0=3 1=1 2=2 3=3  
>>> Array.slice.call( arguments, 1 )  
[]
>>> Array().slice.call( arguments )  
3,1,2,3 0=3 1=1 2=2 3=3  
>>> Array().slice.call( arguments, 1 )  
1,2,3 0=1 1=2 2=3

Basically my misunderstanding boils down to the difference between Array.slice and Array().slice. What exactly is the difference between these two and why does not Array.slice.call behave as expected? (which is giving back all but the first element of the arguments list).

+1  A: 

Array is just a function, albeit a special one (used to initialize arrays). Array.slice is a reference to the slice() function in the Array prototype. It can only be called on an array object and not on the Constructor (i.e. Array) itself. Array seems to behave specially though, as Array() returns an empty array. This doesn't seem to work for non-builtin Constructor functions (there you have to use new). So

Array().slice.call

is the same as

[].slice.call
ujh
A: 

Well,

Looking at http://www.devguru.com/Technologies/ecmascript/quickref/slice.html

Array().slice is a function (constructor)in the array class, It cant be used as a data member. If you didn't want to use the '()' you would need to call it on the array. ie - arguments.slice(1)

Brad8118
A: 

My guess is that Array is a prototype while Array() is an actual array object. Depending on the JavaScript interpretation, directly calling the prototype method of a builtin object type might work or it might not. I don't believe the spec says it has to work, just that calling it on a instantiated object works.

Michael Johnson
A: 

I believe Array is the type and Array() is the constructor function.

Messing around in FireBug:

>>> Array === Array()
false

>>> Array.constructor
Function()

>>> Array().constructor
Array()
roosteronacid
+8  A: 

Not quite.

Watch what happens when you call String.substring.call("foo", 1) and String().substring.call("foo", 2):

>>> String.substring.call("foo", 1)
"1"

>>> String().substring.call("foo", 1)
"oo"

Array.slice is neither properly referencing the slice function attached to the Array prototype nor the slice function attached to any instantiated Array instance (such as Array() or []).

The fact that Array.slice is even non-null at all is an incorrect implementation of the object (/function/constructor) itself. Try running the equivalent code in IE and you'll get an error that Array.slice is null.

This is why Array.slice does not behave correctly (nor does String.substring).

Proof (the following is something one should never expect based on the definition of slice()...just like substring() above):

>>> Array.slice.call([1,2], [3,4])
3,4

Now, if you properly call slice() on either an instantiated object or the Array prototype, you'll get what you expect:

>>> Array.prototype.slice.call([4,5], 1)
[5]
>>> Array().slice.call([4,5], 1)
[5]

More proof...

>>> Array.prototype.slice == Array().slice
true
>>> Array.slice == Array().slice
false
kamens
A: 

How is any call to slice.call() working in the examples provided since a context parameter is not being supplied? Does slice implement it's own call method, thus overriding JavaScript's call method? The call and apply methods take as the first parameter an object to specify the context (this) object to apply to the invocation.

Bill