user3293653
user3293653

Reputation:

Why does underscore alias methods off the prototype chain ?

and then call them using call()?

For example slice can be called directly as such

obj.slice(1);

but underscore does

slice.call(obj, 1);

What is the reason for this?

Upvotes: 2

Views: 89

Answers (2)

Gabs00
Gabs00

Reputation: 1877

I don't have much experience with underscore, but I assume it is due to underscore using array like objects instead of arrays.

In that case, it does not have the methods of an array, and so you have to use the call method.

See examples below:

function List(){
    this.length = arguments.length;

    //arguments is an array like object, not an array, does not have a foreach method
    Array.prototype.forEach.call(arguments, function(val, index){
        this[index] = val;
    }, this);
}

var list = new List(1,2,3,4,5);
console.log(list); //{ '0': 1, '1': 2, '2': 3, '3': 4, '4': 5, length: 5 }

//Cannot use push on on object List
//list.push(6); //TypeError: undefined is not a function

//But you can use call()
Array.prototype.push.call(list, 6);
console.log(list);
//{ '0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6, length: 6 }

http://repl.it/UZX link to the examples above

Edit: I missed something important.

The implimentation of slice that you see is achieved by by setting var slice = Array.prototype.slice

slice.call() is used so that the slice method has a this variable to refer to.

Check out the below example:

var push = Array.prototype.push;

push.call(list, 7);

console.log(list);
//{ '0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6, '6': 7, length: 7 }

List.prototype.push = push;
list.push(8);

console.log(list);
//{ '0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6, '6': 7, '7': 8, length: 8 }

Upvotes: 0

SLaks
SLaks

Reputation: 887413

In case obj.slice isn't what you think it is.

In particular, array-like objects like arguments or NodeLists do not have a slice method.

Upvotes: 1

Related Questions