I am writing a script in which I need to clone arrays in many different places. For this reason, I would like to do the following to emulate a cloning function:
var clone = [].slice.call;
var arr1 = [1,2,3,4,5,6,7,8,9,10];
var arr2 = clone(arr1, 0);
Unfortunately, the above code results in: TypeError: object is not a function
. I realize there are many functions out there to do deep cloning and shallow copies but I just want to use the built in method. Interestingly enough, the following does work:
var clone = [].slice;
var arr1 = [1,2,3,4,5,6,7,8,9,10];
var arr2 = clone.call(arr1, 0);
Does anyone know why the first block doesn't work while the second does? Is there any way to reference a functions call and apply functions without throwing errors when calling the referenced function?
I have to definitely agree with both Felix King and pimvdb. I think the only drawback to using the Function.protoytpe.bind() function is the fact that this is not a function that is available in all browsers (IE6 for example). An alternative would be to use a JavaScript library that provides the curry() function. Another alternative would be to define a function which gives you the ability to retrieve the call function for any other function. Here is a definition that I posted on my blog for such a function which I called getCall():
Now, with this definition, you could do the following to get a reference to the call function of the slice function:
Sweet and simple:
The problem is that
whatever_function.call
is equal toFunction.prototype.call
. Thus, you effectively save a reference toFunction.prototype.call
and the information that it is the slice function is lost.Compare it with a custom function:
A method of keeping the
this
value from being changed is usingFunction.prototype.bind
:Now,
because when calling the
.call
function, thethis
value is bound to the slice function and everything works as expected.You can clone an array by calling
slice
directly:If you want a
clone
function, you can do:If you really want to prototype function (which is not necessary as long as the function is not overwritten):
Why can't you reference
call
orapply
directly?It does not work for the same reason assigning a method of an object to a variable does not "work".
If you call
func.call()
thenthis
insidecall
will be a reference tofunc
, a function object.If you assign
call
to a variable then the context is lost. You have a reference to the genericcall
function. Thus you'd have to pass the correct context (the method you want to applycall
to) as first parameter tocall
again:This is not really an improvement and quite confusing.
call
andapply
are methods that every functions inherits fromFunction.prototype
. Functions don't have their own version of them.[].slice.call === [].splice.call
yieldstrue
.The difference is the scope of the function, i.e. what "this" is. I'm not sure what the correct technical terms are, but the "this" is not the same when a function is called "stand alone" or as a property of an object.
You can however create a function that wraps a call to the function and passes on all the arguments:
For the record, the most common way of doing this is: