简体   繁体   English

调用/绑定/应用与原型

[英]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(); 如果将对象绑定到sayHello(sayHello.bind(user))或使用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.. 我错误地编写了Object.prototype ..而不是指定(我创建的对象).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 . 您不想使用Object.prototype.sayHi = function(){}是,一旦这样做,原型链中所有具有Object都将能够使用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 ). 这是确定的事情添加到创建(和它只是被认为是不好的做法添加到对象的原型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,Apply和Bind实际上与添加到原型稍有不同,Bind和Call and Apply也有所不同。

Call and Apply 打电话申请

Function.call() and Function.apply() use whatever function you are calling or applying at the moment of the call or apply. Function.call()Function.apply()在调用或应用时使用您正在调用或应用的任何函数。

For example, if we wanted to use the forEach() method on a NodeList 例如,如果我们想在NodeList上使用forEach()方法

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. call和apply之间的最大区别在于, call采用可变参数,而apply采用数组。

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. 使用Function.bind()实际上是另一回事。 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". 现在,您可以传递ftorCar并在需要时调用它,它将具有正确的作用域“绑定”。

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. 修改Object.prototype是非常不好的做法,因为每个对象都继承自它,因此,现在创建的每个对象都将具有一个名为sayHi的方法,即使没有属性名称的对象也是如此。

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: 如果要创建自己的类say,可以将sayHi方法添加到原型列表中,因为这样只有该类型的实例才具有该方法:

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. 我倾向于将原型用于我创建的对象,并在内部范围内使用这些原型运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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