1. 共同点
三者共同点都是改变函数内部this指向的方法
2. call用法
var a = 2;
var b = 2;
function func() {
console.log(this.a, this.b)
}
let obj = { a: 1, b: 1 }
func.call(obj)
func.call()
输出结果:
1 1
2 2
解析:
- call的第一个参数是更改后的this指向对象,如果第一个参数不填,在非严格模式下,指向的是全局;但是在严格模式下,指向的就是undefined了,所以得注意一下
- func.call(obj)中,this指向变化了,指向了obj,所以输出的结果是1 1
- func.call()中,在非严格模式下,默认改变了this指向到全局,所以输出2 2
3. call和apply区别
call和apply唯一的区别就是,传参形式不一样,call是一个个写入传进去,而apply是用一个数组包起来传进去
obj.call(thisObj, arg1, arg2, …);
obj.apply(thisObj, [arg1, arg2, …]);
4. call和bind的区别
call和bind语法完全一模一样,唯一不同的是call和apply是立即执行;而bind并不是立即执行,要执行得绑定之后,再去调用这个函数
var a = 2;
var b = 2;
function func() {
console.log(this.a, this.b)
}
let obj = { a: 1, b: 1 }
func.bind(obj)()
// 输出结果:1 1
5. 总结
- call,apply,bind都是改变函数this指向的
- call和apply用法基本上一致,唯一不同点是apply传参是以数组的方式传入,而call是一个个传入
- bind用法和call基本上一致,唯一不同的是call和apply是立即执行的,而bind不是立即执行
6. 面试真题
var a = 1;
function fn1() {
var a = 2;
console.log(this.a + a)
}
function fn2() {
var a = 10;
fn1();
}
fn2()
var Fn3 = function () {
this.a = 3
}
Fn3.prototype = {
a: 4
}
var fn = new Fn3()
fn1.call(fn)
输出结果:
3 (1+2)
5 (3+2)
讲解:
- 执行fn2()的时候,fn1中的this指向是全局,相当于是1+2=3;则输出结果是3
- fn1通过call改变this指向到了Fn3,此时可以在Fn3上一层层找到a,此时在构造函数中就有a所以此时是3+2=5;如果构造函数中没有对this.a赋值,则会沿着原型链一层层找上去,找到在 Fn3.prototype中有声明了一个a,所以如果构造函数中没有对this.a进行赋值,则此时的结果应该会是4+2=6