简体   繁体   中英

Call/Bind/Apply vs prototype

In the following code:

function User(name) {
    this.name = name;
}

var user = new User('Jason Bourne');

User.prototype.sayHi = function() {
    return 'Hi ' + this.name;
};

var sayHello = function() {
    return 'Hello ' + this.name;
};

Both functions will give me the same result if I bind the object to sayHello (sayHello.bind(user)) or if I use user.sayHi();

So my question is, is there a reason to use one method over the other? I thought I've read somewhere that creating things on prototype is discouraged, if so why?

CORRECTION:

\n

I erroneously wrote Object.prototype.. instead of specifying (Object I create).prototype..

The reason you don't want to use Object.prototype.sayHi = function(){} is that once you do, everything that has Object in its prototype chain will be able to use sayHi . That's the core of prototypical inheritance.

It's OK to add things to the prototype of objects that you create (and it's just considered bad practice to add to Object.prototype ). Just understand that when you do, anything in your objects prototype chain will be able to use that function.

function sayHello() {
    console.log("hello");
}

// Bad
Object.prototype.hello = sayHello;
Date.hello(); // Prints hello

Call, Apply, and Bind are actually slightly different from adding to prototype and Bind is also different from Call and Apply as well.

Call and Apply

Function.call() and Function.apply() use whatever function you are calling or applying at the moment of the call or apply.

For example, if we wanted to use the forEach() method on a NodeList

var els = document.querySelectorAll("div");
Array.prototype.forEach.call(els, function(el){
    el.classList.add("someClass");

The big difference between call and apply is that call takes a variadic argument and apply takes an Array.

function say() {
    console.log(arguments);
}
say.call(this, "a", "b");
say.apply(this, ["a", "b"]);

Bind

Using Function.bind() is actually a different thing though. Bind lets you create a context binding where you can call a function from a specific context when you want.

function honk() {
    console.log(this.sound);
}

function Car() {
    this.sound = "honk";
}

function Van(){
    this.sound = "beep";
}
var c = new Car();
var v = new Van();

var ftorCar = honk.bind(c);
var ftorVan = honk.bind(v);

ftorCar(); // prints honk
ftorVan(); // prints beep

You can now pass ftorCar around and call it when you want to and it will have the correct scope "binding".

It's very bad practice to modify the Object.prototype because every object inherits from it, so then every object created now will have a method called sayHi, even objects which do not have the property name.

If you were to create your own class say, it is acceptable to add the sayHi method to the prototype list because then only instances of the type will have that method:

function Person(name){
   this.name = name;
}

Person.prototype.sayHi = function() { return 'Hi ' + this.name; }

As for picking one way or another, I would say it's preference mostly. I tend to use prototypes for objects that I create and functions using those prototypes in an internal scope.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM