Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

call and apply in javascript [duplicate]

Tags:

javascript

Possible Duplicate:
What’s the meaning to chain call and apply together?

I found some codes like this:

function fun() {
    return Function.prototype.call.apply(Array.prototype.slice, arguments);
}

I know the call and apply in js,however I am confused when they come together.

Then I wonder if

Function.prototype.call.apply(Array.prototype.slice, arguments)

is the same as :

Array.prototype.slice.apply(arguments);

If not,what does the first line do?

like image 376
hguser Avatar asked May 04 '26 16:05

hguser


1 Answers

Alright, let's tackle this problem via substitution. We start with:

Function.prototype.call.apply(Array.prototype.slice, arguments);

What we know:

  1. Function.prototype.call is a function.
  2. The this pointer of call points to Function.prototype.
  3. We use apply to change the this pointer of call to Array.prototype.slice.
  4. arguments is applied (not passed as a parameter) to call.

Thus the above statement is equivalent to:

Array.prototype.slice.call(arguments[0], arguments[1], ...);

From this we see:

  1. Array.prototype.slice is a function.
  2. The this pointer of slice points to Array.prototype.
  3. We use call to change the this pointer of slice to arguments[0].
  4. arguments[1], ... are passed as parameters to slice.

This is the same as:

arguments[0].slice(arguments[1], ...);

The advantage of this is that we're creating a fast unbound wrapper for slice in a single line.

Edit: A better way to create fast unbound wrappers is as follows (note that it may not work in some older browsers, but you don't really need to worry about that now - you may always use a shim for browsers which don't support bind):

var slice = Function.prototype.call.bind(Array.prototype.slice);

This is the same as:

function slice() {
    return Function.prototype.call.apply(Array.prototype.slice, arguments);
}

How it works:

  1. Function.prototype.call is a function.
  2. The this pointer of call points to Function.prototype.
  3. We use bind to change the this pointer of call to Array.prototype.slice.
  4. bind returns a function whose arguments are applied to call.

Bonus: If your style of programming is highly functional, like mine is, then you would find that is piece of code is very useful:

var funct = Function.prototype;
var obj = Object.prototype;
var arr = Array.prototype;

var bind = funct.bind;

var unbind = bind.bind(bind);
var call = unbind(funct.call);
var apply = unbind(funct.apply);

var classOf = call(obj.toString);
var ownPropertyOf = call(obj.hasOwnProperty);
var concatenate = call(arr.concat);
var arrayFrom = call(arr.slice);
  1. Using this you may easily create unbound wrappers using either call or apply.
  2. You may use classOf to get the internal [[Class]] of a value.
  3. You may use ownPropertyOf inside for in loops.
  4. You may use concatenate to join arrays.
  5. You may use arrayFrom to create arrays.
like image 139
Aadit M Shah Avatar answered May 06 '26 07:05

Aadit M Shah



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!