协慌网

登录 贡献 社区

JavaScript call()和 apply()与 bind()?

我已经知道applycall是用于设置this相似函数(函数的上下文)。

区别在于我们发送参数的方式(手动 vs 数组)

题:

但是什么时候应该使用bind()方法呢?

var obj = {
  x: 81,
  getX: function() {
    return this.x;
  }
};

alert(obj.getX.bind(obj)());
alert(obj.getX.call(obj));
alert(obj.getX.apply(obj));

jsbin

答案

如果您希望以后在特定的上下文中调用该函数,请使用.bind() ,这在事件中很有用。若要立即调用该函数并修改上下文,请使用.apply() .call().apply()

调用 / 应用立即调用该函数,而bind返回一个函数,该函数稍后执行时,将为调用原始函数设置正确的上下文。这样,您可以在异步回调和事件中维护上下文。

我经常这样做:

function MyObject(element) {
    this.elm = element;

    element.addEventListener('click', this.onClick.bind(this), false);
};

MyObject.prototype.onClick = function(e) {
     var t=this;  //do something with [t]...
    //without bind the context of this function wouldn't be a MyObject
    //instance as you would normally expect.
};

我在 Node.js 中将它广泛用于异步回调,我想为其传递成员方法,但仍希望上下文成为启动异步操作的实例。

一个简单,简单的 bind 实现是:

Function.prototype.bind = function(ctx) {
    var fn = this;
    return function() {
        fn.apply(ctx, arguments);
    };
};

它还有更多的功能(就像传递其他 args 一样),但是您可以阅读更多有关它的内容,并查看MDN 上的实际实现。

希望这可以帮助。

他们都附加到这个函数(或对象)不同的是在函数调用(见下文)。

调用附加到这个函数并立即执行的功能:

var person = {  
  name: "James Smith",
  hello: function(thing) {
    console.log(this.name + " says hello " + thing);
  }
}

person.hello("world");  // output: "James Smith says hello world"
person.hello.call({ name: "Jim Smith" }, "world"); // output: "Jim Smith says hello world"

绑定附加到这个函数和其需要被这样分开调用:

var person = {  
  name: "James Smith",
  hello: function(thing) {
    console.log(this.name + " says hello " + thing);
  }
}

person.hello("world");  // output: "James Smith says hello world"
var helloFunc = person.hello.bind({ name: "Jim Smith" });
helloFunc("world");  // output: Jim Smith says hello world"

或像这样:

...    
var helloFunc = person.hello.bind({ name: "Jim Smith" }, "world");
helloFunc();  // output: Jim Smith says hello world"

applycall类似,不同之处在于apply类似于一个数组对象,而不是一次列出一个参数:

function personContainer() {
  var person = {  
     name: "James Smith",
     hello: function() {
       console.log(this.name + " says hello " + arguments[1]);
     }
  }
  person.hello.apply(person, arguments);
}
personContainer("world", "mars"); // output: "James Smith says hello mars", note: arguments[0] = "world" , arguments[1] = "mars"

以 SIMPLEST 形式回答

  • 调用会调用该函数,并允许您逐个传递参数。
  • Apply调用该函数,并允许您将参数作为数组传递。
  • Bind返回一个新函数,使您可以传入 this 数组和任意数量的参数。

应用,调用,绑定示例

呼叫

var person1 = {firstName: 'Jon', lastName: 'Kuperman'};
var person2 = {firstName: 'Kelly', lastName: 'King'};

function say(greeting) {
    console.log(greeting + ' ' + this.firstName + ' ' + this.lastName);
}

say.call(person1, 'Hello'); // Hello Jon Kuperman
say.call(person2, 'Hello'); // Hello Kelly King

应用

var person1 = {firstName: 'Jon', lastName: 'Kuperman'};
var person2 = {firstName: 'Kelly', lastName: 'King'};

function say(greeting) {
    console.log(greeting + ' ' + this.firstName + ' ' + this.lastName);
}

say.apply(person1, ['Hello']); // Hello Jon Kuperman
say.apply(person2, ['Hello']); // Hello Kelly King

绑定

var person1 = {firstName: 'Jon', lastName: 'Kuperman'};
var person2 = {firstName: 'Kelly', lastName: 'King'};

function say() {
    console.log('Hello ' + this.firstName + ' ' + this.lastName);
}

var sayHelloJon = say.bind(person1);
var sayHelloKelly = say.bind(person2);

sayHelloJon(); // Hello Jon Kuperman
sayHelloKelly(); // Hello Kelly King

什么时候使用

通话和申请都可以互换。只需确定发送数组还是用逗号分隔的参数列表比较容易。

通过记住 Call 是逗号(分隔列表),Apply 是 Array,我一直记得是哪个。

绑定有点不同。它返回一个新函数。 Call and Apply 立即执行当前功能。

绑定在很多方面都很有用。我们可以使用它来管理上面的示例中的函数。我们可以采用一个简单的 hello 函数并将其转换为 helloJon 或 helloKelly。我们也可以将其用于诸如 onClick 之类的事件,这些事件我们不知道何时触发,但我们知道我们希望它们具有什么上下文。

参考: codeplanet.io