引言:this是在面试和工作中经常会遇到的东西,也是必须要掌握的内容
一、this的指向
一般情况下,谁调用,this就指向谁
下面来看几个例子
var a = 1;
function fn() {
console.log(this.a);
}
fn(); // 输出1
在这里this指向的就是Window,验证打印一下this看看
function fn() {
console.log(this);
}
fn(); // 输出Window
console.log(this); // 输出Window
这是普通函数中调用和在外部调用this的情况,现在再来看一个例子
var a = 1;
var obj = {
a: 2,
fn: function() {
console.log(this.a);
}
}
obj.fn(); // 输出2
这里可以发现this指向的就不再是Window,而是obj。发现没有这个例子中是用obj调用的fn,所以fn中的this就指向obj。
上个例子中在外部直接调用fn,this指向的就是外部的环境Window。
所以可以得出结论,谁调用,this就指向谁。
二、修改this的指向
可以通过call、apply、bind来修改this的指向
看一个例子
example: 希望输出weapon的name
var garen = {
name: "盖伦",
age: 22,
say: function () {
console.log("我的武器是" + this.name);
},
};
var weapon = {
name: "暴风大剑",
};
garen.say(); // 输出:我的武器是盖伦
遇到这种情况时,就需要修改this的指向
这里有几种方法可以修改
1. call
call方法可以接收多个参数
call(修改后的this指向, 参数1, 参数2, 参数3...)
修改后的example
var garen = {
name: "盖伦",
age: 22,
say: function () {
console.log("我的武器是" + this.name);
},
};
var weapon = {
name: "暴风大剑",
};
garen.say.call(weapon) // 输出:我的武器是暴风大剑
call()传入多个参数的使用
var garen = {
name: "盖伦",
age: 22,
say: function (desc) {
console.log("我的武器是" + this.name, desc);
},
};
var weapon = {
name: "暴风大剑",
};
garen.say.call(weapon, "我没有特色", "我很肉") // 输出:我的武器是暴风大剑 我没有特色
这里可以看到输出的内容少了第三个参数,那是因为desc只传递了第二个参数,第三个参数没有传递。那传递多个参数可以通过新增参数的方式,或者使用 ES6 的扩展运算符来完成。
最终代码
var garen = {
name: "盖伦",
age: 22,
say: function (...desc) {
console.log("我的武器是" + this.name, ...desc);
},
};
var weapon = {
name: "暴风大剑",
};
garen.say.call(weapon, "我没有特色", "我很肉") // 输出:我的武器是暴风大剑 我没有特色 我很肉
2. apply
apply和call的区别就在于接收的参数,call能接收多个参数,但apply只能接收2个参数。
第一个和call一样,都是this的指向。
第二个参数是一个数组,将call中的剩余参数都放到了这个数组中。
apply(修改后的this指向, [参数1, 参数2, 参数3...])
仅此而已,其他用法完全一样,只是接收参数的方式改变了。
那 example 用apply的写法
var garen = {
name: "盖伦",
age: 22,
say: function (...desc) {
console.log("我的武器是" + this.name, ...desc);
},
};
var weapon = {
name: "暴风大剑",
};
// 只有这里修改了
garen.say.apply(weapon, ["我没有特色", "我很肉"]) // 输出:我的武器是暴风大剑 我没有特色 我很肉
3. bind
bind和call也很相似,不过返回结果不同,bind是返回一个新函数,call和apply不会返回新函数,而是直接执行原函数,并返回函数执行的结果
bind(修改后的this指向, 参数1, 参数2, 参数3...)()
那 example 用apply的写法
var garen = {
name: "盖伦",
age: 22,
say: function (...desc) {
console.log("我的武器是" + this.name, ...desc);
},
};
var weapon = {
name: "暴风大剑",
};
// 只有这里修改了
garen.say.bind(weapon, "我没有特色", "我很肉")() // 输出:我的武器是暴风大剑 我没有特色 我很肉
三、总结
一般情况下this指向调用它的实例,但也可以手动修改this的指向,call、apply、bind都是用来修改this的指向的,区别在于:
call接收多个参数,执行原函数,返回结果apply接收两个参数,第二个参数是数组,执行原函数,返回结果bind接收多个参数,不会执行函数,只会返回新函数,所以使用时要再调用一次
call(this,param1,param2,param3...)
apply(this,[param1,param2,param3...])
bind(this,param1,param2,param3...)()
特别注意:this参数为null的情况
call、apply、bind的第一个this参数可以为null
如果是null或undefined的话,修改后的指向会变成window
call、apply、bind实现原理
在了解了用法后可以对其实现原理进行了解,点击跳转 手写call、apply、bind思路及实现