# JavaScript 中 call()、apply()、bind() 的用法

先看两个例子

# 例子1

var name = "小布",age = 18
var obj = {
name: "小红",
objAge: this.age,
myFun: function(){
console.log(`姓名:${this.name},年龄:${this.age}`)
}
}
console.log(obj.objAge) //18
console.log(obj.myFun()) //姓名:小红,年龄:undefined

# 例子2

var name = "小布"
function showName() {
console.log(this.name)
}

showName() //小布

**结论:**例子1中的 objAge中的 this 指向 window,因此拿到的值 是 18. myFun 中的 this 指向的是 obj对象,因此 拿到 name 是 小红, 但是 对象中并没有age 因此 打印的值为 undefined。例2中 函数一样的,this指向的是 window。

**存在问题:**由于函数中this指向不是很明确,有时候需要改变this指向,因此出现了call()、apply()、bind()三个方法。这三个方法的出现就是改变this指向的。

如:

var name = "小布", age = 18
var obj = {
name: "小红",
objAge: this.age,
myFun: function(){
console.log(`姓名:${this.name},年龄:${this.age}`)
}
}

var otherObj = {
name: "张三",
age: "99"
}

console.log(obj.myFun()) //姓名:小红,年龄:undefined
console.log(obj.myFun.call(otherObj)) //姓名:张三,年龄:99
console.log(obj.myFun.apply(otherObj)) //姓名:张三,年龄:99
console.log(obj.myFun.bind(otherObj)()) //姓名:张三,年龄:99

call,apply,bind 三个方法除了bind方法后面需要多个 () 外,其余没有区别,且返回结果都一致

结论: bind返回的是一个新的函数,因此使用bind时需要加个()调用。且call,apply,bind的第一个参数为 this的指向对象。

# 对比call、apply、bind传参情况下的区别

var name = "小布", age = 18
var obj = {
name: "小红",
objAge: this.age,
myFun: function(from,to) {
console.log(`姓名:${this.name} 年龄:${this.age},来自${from}去往${to}`)
}
}

var otherObj = {
name: "李四",
age: 88
}

console.log(obj.myFun("厦门","北京")) //姓名:小红 年龄:undefined,来自厦门去往北京
console.log(obj.myFun.call(otherObj,"厦门","北京")) //姓名:李四 年龄:88,来自厦门去往北京
console.log(obj.myFun.call(otherObj,["厦门","北京"])) //姓名:李四 年龄:88,来自厦门,北京去往undefined
console.log(obj.myFun.call(otherObj,["厦门","北京"],"漳州")) //姓名:李四 年龄:88,来自厦门,北京去往漳州
console.log(obj.myFun.apply(otherObj,["厦门","北京"])) //姓名:李四 年龄:88,来自厦门去往北京
console.log(obj.myFun.bind(otherObj,"厦门","北京")()) //姓名:李四 年龄:88,来自厦门去往北京
console.log(obj.myFun.bind(otherObj,["厦门","北京"])()) //姓名:李四 年龄:88,来自厦门,北京去往undefined
console.log(obj.myFun.bind(otherObj,["厦门","北京"],"漳州")()) //姓名:李四 年龄:88,来自厦门,北京去往漳州

从上面的结果不难看出

call、apply、bind这三个函数的第一个参数都是this的指向对象,主要区别就是第二个参数

call 参数是直接放进去的,第二个第三个第n个参数全都用逗号分隔,直接放到后面obj.myFun.call(otherObj,"厦门",..., "string")

apply 的所有参数必须放在一个数组里面传进去,obj.myFun.apply(otherObj,["厦门",..., "string"])

bind除了返回是函数以外,他的参数和call一样。

当然,三者的参数不限定是 string 类型,允许是各种类型,包括函数 、 object 等等!

阅读原文 (opens new window)