Call/Bind/Apply 对比原型

Call/Bind/Apply vs prototype

在下面的代码中:

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;
};

如果我将对象绑定到 sayHello (sayHello.bind(user)) 或者如果我使用 user.sayHi();

,这两个函数都会给我相同的结果

所以我的问题是,是否有理由使用一种方法而不是另一种方法?我想我在某处读到过不鼓励在原型上创建东西,如果是的话,为什么?

更正:

我错误地写了 Object.prototype.. 而不是指定 (Object I create).prototype..

修改 Object.prototype 是非常糟糕的做法,因为每个对象都继承自它,所以现在创建的每个对象都会有一个名为 sayHi 的方法,即使对象没有 属性 名称.

如果您要创建自己的 class say,可以将 sayHi 方法添加到原型列表中,因为这样只有该类型的实例才会有该方法:

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

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

至于选择一种或另一种方式,我会说主要是偏好。我倾向于为我创建的对象使用原型,并在内部范围内使用这些原型。

您不想使用 Object.prototype.sayHi = function(){} 的原因是,一旦您这样做,其原型链中具有 Object 的所有内容都将能够使用 sayHi。这就是原型继承的核心。

可以向 创建的对象原型添加内容(添加到 Object.prototype 被认为是不好的做法)。只要明白当你这样做时,你的对象原型链中的任何东西都将能够使用该功能。

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

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

Call、Apply 和 Bind 实际上与添加到原型略有不同,Bind 也与 Call 和 Apply 不同。

致电申请

Function.call() and Function.apply() 在调用或应用时使用您正在调用或应用的任何函数。

例如,如果我们想在 NodeList

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

call 和 apply 之间的最大区别在于 call 采用可变参数而 apply 采用数组。

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

绑定

使用 Function.bind() 实际上是另一回事。 Bind 允许您创建上下文绑定,您可以在其中根据需要从特定上下文调用函数。

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

您现在可以传递 ftorCar 并在需要时调用它,它将具有正确的范围 "binding"。