call、apply、bind三个都是函数的方法
由于有三个方法,可能会纠结学哪个的时候,这个时候我们就先盯着call学! (学会一个的用法,其他两个用法只有略微的不同...)
call可以调用函数, 并且改变函数中this
来个很简单的小案例:
let dog = {
name: '旺旺',
sayName(){ //此时有个方法打印出 name
console.log('我的名字是'+this.name)
}
}
let cat = {
name: '喵喵'
}
dog.sayName()
输出结果:
毫无疑问,名字是旺旺,和喵喵没什么关系
那我们想让name和喵喵有关系的话, 就得使用call改变this指向喵喵了
很简单, 只需要加一个call就能办到
let dog = {
name: '旺旺',
sayName(){
console.log('我的名字是'+this.name)
}
}
let cat = {
name: '喵喵'
}
dog.sayName.call(cat) // 不同点
这里我们加了一个call, call的参数直接写 cat 改变this指向
来看打印结果:
改变成功!
再来一个传参数的小案例:
在原来的基础下再添加一个方法
let dog = {
name: '旺旺',
sayName(){
console.log('我的名字是'+this.name)
},
eat(food){
console.log('我喜欢吃'+food)
}
}
let cat = {
name: '喵喵'
}
dog.eat('骨头') // 添加参数
输出结果:
毫无疑问,喜欢吃的是骨头,喵喵还是没什么关系
继续使用call让 cat 参与进来
let dog = {
name: '旺旺',
sayName(){
console.log('我的名字是'+this.name)
},
eat(food1, food2){ // 注意这儿形参有两个
console.log('我喜欢吃'+food)
}
}
let cat = {
name: '喵喵'
}
**看这里!!!**
dog.eat.call(cat)
//注意这里有问题的 打印结果为: 喵喵喜欢吃的是undefined
// 因为没有跟参数...
正确传参:
dog.eat.call(cat,'鱼') // 只需要逗号隔开 加参数就可以
如果传两个参数呢?
dog.eat.call(cat,'鱼','肉') // 往后面在继续加,
打印结果:
这是call的的使用 (改变this指向, 以及传参)
再说一下apply()
还是一样的例子用法
与call不同点: 以数组方式去传参,
let dog = {
name: '旺旺',
sayName(){
console.log('我的名字是'+this.name)
},
eat(food1, food2){ // 注意这儿形参有两个
console.log('我喜欢吃'+food)
}
}
let cat = {
name: '喵喵'
}
看这儿
dog.eat.apply(cat,['鱼','肉']) // 打印结果 我喜欢吃鱼,肉
打印结果和上面相同就不放图了
接下来再说bind:
bind传参方式与call相同, 不同的是bind不会调用这个函数,而是把函数作为返回值给返回回来;
let dog = {
name: '旺旺',
sayName(){
console.log('我的名字是'+this.name)
},
eat(food1, food2){ // 注意这儿形参有两个
console.log('我喜欢吃'+food)
}
}
let cat = {
name: '喵喵'
}
看这儿
let bind = dog.eat.bind(cat,'鱼','肉') 把返回值赋值给变量
bind()
打印结果:
总结:
三个方法相同的地方:
- 三者都是用来改变函数的this对象的指向的
- 三者第一个参数都是this要指向的对象,也就是想指定的上下文
- 三者都可以利用后续参数传参
三个方法不同的地方:
call: 对象.call(对象,'1','2') 依次往后传的方式传参
apply: 把实参以数组方式去传参
bind: 把函数以返回值的形式返回
继承: 子类可以使用父类的方法
// 在这我们有两个函数
function Animal() {
当代码执行到这儿的时候this发生了改变
this.test = function () {
console.log('打印成功')
}
}
function Cat(){
//只需要这一行代码改变this指向cat
Animal.call(this)
}
需求是调用cat函数 可以使用Animal里面的test和eat方法
let cat = new Cat()
cat.test() // 打印成功