this 的指向规则
JavaScript 中 this 的五种绑定规则及优先级
问题
JavaScript 中 this 的指向是什么?有哪些绑定规则?
解答
this 的值在函数调用时确定,取决于函数的调用方式。共有五种绑定规则。
1. 默认绑定
独立函数调用时,this 指向全局对象(严格模式下为 undefined)。
function foo() {
console.log(this)
}
foo() // 非严格模式:window / global
// 严格模式:undefined
2. 隐式绑定
函数作为对象方法调用时,this 指向该对象。
const obj = {
name: 'Alice',
sayName() {
console.log(this.name)
}
}
obj.sayName() // 'Alice'
// 隐式丢失:将方法赋值给变量后调用
const fn = obj.sayName
fn() // undefined(this 指向全局)
3. 显式绑定
使用 call、apply、bind 显式指定 this。
function greet(greeting) {
console.log(`${greeting}, ${this.name}`)
}
const person = { name: 'Bob' }
// call:参数逐个传递
greet.call(person, 'Hello') // 'Hello, Bob'
// apply:参数以数组传递
greet.apply(person, ['Hi']) // 'Hi, Bob'
// bind:返回绑定后的新函数
const boundGreet = greet.bind(person)
boundGreet('Hey') // 'Hey, Bob'
4. new 绑定
使用 new 调用构造函数时,this 指向新创建的实例对象。
function Person(name) {
// this 指向新创建的实例
this.name = name
}
const p = new Person('Charlie')
console.log(p.name) // 'Charlie'
5. 箭头函数
箭头函数没有自己的 this,继承外层作用域的 this(词法绑定)。
const obj = {
name: 'David',
// 普通函数
sayName() {
// 箭头函数继承 sayName 的 this
const inner = () => {
console.log(this.name)
}
inner()
},
// 箭头函数作为方法(不推荐)
arrowMethod: () => {
console.log(this.name) // undefined,this 指向外层(全局)
}
}
obj.sayName() // 'David'
obj.arrowMethod() // undefined
优先级
当多种规则同时适用时,按以下优先级判断:
// new 绑定 > 显式绑定 > 隐式绑定 > 默认绑定
function foo(val) {
this.a = val
}
const obj = {}
const bar = foo.bind(obj)
bar(2)
console.log(obj.a) // 2
// new 可以覆盖 bind
const baz = new bar(3)
console.log(obj.a) // 2(未改变)
console.log(baz.a) // 3(new 优先)
关键点
- 默认绑定:独立调用指向全局,严格模式为
undefined - 隐式绑定:谁调用指向谁,注意隐式丢失问题
- 显式绑定:
call/apply立即执行,bind返回新函数 - new 绑定:
this指向新创建的实例对象 - 箭头函数:无自身
this,继承定义时的外层this - 优先级:new > 显式 > 隐式 > 默认
目录