1. 共同点
三者共同点都是改变函数内部this指向的方法
2. call用法
ini
复制代码
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是用一个数组包起来传进去
ini
复制代码
obj.call(thisObj, arg1, arg2, …); obj.apply(thisObj, [arg1, arg2, …]);
4. call和bind的区别
call和bind语法完全一模一样,唯一不同的是call和apply是立即执行;而bind并不是立即执行,要执行得绑定之后,再去调用这个函数
javascript
复制代码
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. 面试真题
ini
复制代码
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)
输出结果:
scss
复制代码
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