js中的this指向很灵活,有个说法是“谁调用this就指向谁”
一、this的规律
1.在函数体内,严格模式下,this指向undefined,非严格模式下,指向全局对象window
2.用new方法调用函数,构造函数内的this会被绑定到新创建的对象
3.用call、apply、bind方法调用函数时,函数体内的this会绑定到指定参数对象上
4.对象调用函数时,函数内this被绑定到该对象
5.箭头函数中,this指向外层(函数或全局)作用域
二、call、apply、bind、new
1.一般叫call、apply、bind的this绑定为显式绑定,调用关系确定this指向的称为隐式绑定
2.call、apply直接调用函数,函数体中的this指向参数中的对象,bind返回一个新函数,函数体中的this指向参数中的对象,需要手动调用
3.call、apply、bind的优先级比一般的高,以下例子为对象调用函数,其this指向被call、apply、bind修改
例:
function f1(a){
console.log(this.a);
}
const obj1 = {
a:1,
f1:f1
}
const obj2 = {
a:2,
f1:f1
}
const obj3 = {
a:3,
f1:f1
}
obj1.f1.call(obj2) //2
obj2.f1.call(obj1) //1
obj2.f1.bind(obj1)() //1
4.new比bind的优先级高
function f1(a){
this.a = a
}
const obj1 = {}
var fun = f1.bind(obj1)
fun(2)
console.log(obj1.a); // 2
var obj2 = new fun(3)
console.log(obj2.a); //3
由结果可见,bind把返回了一个把this指向obj1的函数fun,当fun函数作为构造函数时,this指向被修改了,指向了新创建的对象obj2
三、箭头函数的this指向
先看一段代码,输出结果应该是什么呢
const obj = {a:1}
var b = ()=>{
console.log(this.a);
}
b.call(obj)
这里输出undefined,因为箭头函数的this指向外层作用域,函数或者全局
function fun(){
return a => {
console.log(this.a);
}
}
const obj1 = {
a:1
}
const obj2 = {
a:2
}
var fuc = fun.call(obj1)
fuc.call(obj2)
输出结果是1。
为什么呢,按我的理解是:第一次调用fun,fun内的this指向obj1,此时箭头函数的外层作用域就是fun函数,所以箭头函数的this指向fun函数内的this,也就是obj1,然后返回这个箭头函数。fuc.call(obj2) 调用这个fuc函数时,将函数体的this指向obj2,而第一个例子表明,此时的箭头函数不会指向obj2,而是会指向全局。然而这个箭头函数的this已经指向obj1,箭头函数的this指向无法被修改,所以this不会指向全局
再来一个例子:
var fun = () => a => {
console.log(this.a);
}
const obj1 = {
a:1
}
const obj2 = {
a:2
}
var fuc = fun.call(obj1)
fuc.call(obj2)
这回能箭头函数返回一个箭头函数,输出结果会是什么呢
输出结果为undefined,由第一个例子表明,fun函数就算用call将函数体内的this指向改成obj1,它还是会去外层作用域获取this指向,这里外层作用域为全局,fuc接收fun函数返回箭头函数,把其函数体内this指向改为obj2,其结果也相同,去外层作用域全局获取this指向