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"。
在下面的代码中:
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"。