call、apply、bind 的用法分别

173 阅读2分钟

什么是call

JS中的call方法可以用来代替另一个对象调用一个方法。
call 方法可将一个函数的对象上下文从初始的上下文改变为由 this 指定的新对象。

语法:f.call(asThis, input1,input2)

call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。 其中 asThis 会被当做 this,[input1,input2] 会被当做 参数(arguments)。

比如:

function f(){
    'use strict'
    console.log(this)
    console.log(arguments)
    return undefined
}
f.call(1,2,3) // this 为 1,arguments 为 [2,3]

var a = {
    name: '小明',
    age: 18,
    say: function (school, grade) {
        console.log(this.name, "今年"+this.age+"岁,在"+school+"上"+grade)
    }
}
var b={
    name: '小王',
    age: 16
}
a.say.call(b, "中心小学", "六年级")  //小王 今年16 岁,在中心小学上六年级

上面例子意思是把对象b,参数给a,让a以它自己的方法调用,返回结果。
call方法简单理解就是,只要你给出我需要的信息参数给我,我就帮你调用这个方法,计算结果返还给你。

复杂一点的:

function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = 'food';
}

console.log(new Food('cheese', 5).name);   //  "cheese"

apply

call() 方法接受一个或多个参数。

apply() 方法只接受数组形式的参数。

如果要使用数组而不是参数列表,则 apply() 方法非常方便。

语法:f.apply(thisArg, [argsArray])

apply 可以使用数组字面量(array literal),如 fun.apply(this, ['eat', 'bananas'])或数组对象如 fun.apply(this, new Array('eat', 'bananas'))


例如:

var person = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
}
var person1 = {
  firstName:"John",
  lastName: "Doe"
}
person.fullName.apply(person1, ["Oslo", "Norway"]);
//John Doe,Oslo,Norway

bind

bind创建了一个函数,当这个事件绑定在被调用的时候,它的 this 关键词会被设置成被传入的值(这里指调用bind()时传入的参数)。因此,这里我们传入想要的上下文this(其实就是foo),到bind()函数中。然后,当回调函数被执行的时候,this便指向foo对象。

call apply返回函数结果, bind 返回的是新函数
bind 返回对应函数的引用,便于稍后调用;
apply 、call 则是立即调用。

以下例子很容易混淆:

this.x = 9;    // 在浏览器中,this 指向全局的 "window" 对象
var module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX(); // 81

var retrieveX = module.getX;
retrieveX();   
// 返回 9 - 因为函数是在全局作用域中调用的

// 创建一个新函数,把 'this' 绑定到 module 对象
// 新手可能会将全局变量 x 与 module 的属性 x 混淆
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81

当然,这三个用法还有相似之处:
1、都是用来改变函数的this对象的指向
2、第一个参数都是this要指向的对象
3、都可以利用后续参数传参