在JavaScript中this指向很灵活,有一种说法是:“谁调用它,this就指向谁”,也就是说,this的指向是在调用是确定的,但是这样说并不全面,我们进行总结一下。
关于this问题,有几条死规定:
1、全局环境下的this
在函数体中,非显式或者隐式地简单调用函数时,在严格模式下,函数中的this会被绑定到underfined上,在非严格模式下则会被绑定到全局对象window/global上。
function f1() {
console.log(this)
}
function f2() {
'use strict'
console.log(this)
}
f1() //window
f2() //undefined
2、上下文对象调用中的this
当存在复杂的调用关系时,this会指向最后调用它的对象。
const person = {
name: 'Lucas',
brother: {
fn: function(){
return this.name
}
}
}
console.log(person.brother.fn())
3、通过bind、call、apply改变this指向
一般通过call/apply/bind方法显式调用函数时,函数体内的this会被绑定到指定参数的对象上。
他们都式改变相关函数this指向的,但是call和aplly是直接进行相关函数调用的;bind不会执行相关函数,而是返回一个新的函数,这个新的函数已经自动绑定了新的this指向,开发者可以手动调用它。
4、构造函数和this
一般通过上下文对象调用函数时,函数体内的this会被绑定到该对象上。
如果构造函数中显示返回一个值,且返回的是一个对象(返回复杂类型),那么this就指向这个返回的对象,如果返回的不是一个对象(返回基本类型,那么this仍然指向实例。
5、箭头函数中的this
在箭头函数中,this的指向是由外层(函数或全局)作用域决定的。
下面来看一段代码,在这段代码中this出现在sidetimeout()的匿名函数中,因此this指向window对象。
const foo = {
fn:function () {
setTimeout(function(){
console.log(this)
})
}
}
console.log(foo.fn())
如果需要让this指向foo这个对象,则可以巧用箭头函数来解决,代码如下:
const foo = {
fn:function () {
setTimeout(() =>{
console.log(this)
})
}
}
console.log(foo.fn())
//{fn:f}
单纯的箭头函数中的this指向问题很简单,但是如果综合所有情况并结合this的优先级进行考察,那么这时的this指向并不容易确定。
6、this优先级
我们常常把call、apply、bind、new对this进行绑定的情况称为显示绑定,而把根据调用关系确定this指向的情况称为隐式绑定。
call、apply的显示绑定一般来说优先级更高,new绑定的优先级比显式bind绑定的更高。