主题
this 指向
提示
this 关键字是 JavaScript 中最复杂的机制之一。它的指向完全取决于函数调用的位置(Call Site),而不是函数声明的位置。
核心规则:this 的四种绑定
判断 this 指向,主要看函数是如何被调用的。
1. 默认绑定 (Default Binding)
当函数独立调用(不带任何修饰符)时,this 指向全局对象。
- 在浏览器中指向
window。 - 在 Node.js 中指向
global。 - 严格模式 (
'use strict') 下,this为undefined。
js
function sayHi() {
console.log(this.name)
}
var name = 'Global'
sayHi() // 'Global' (非严格模式)2. 隐式绑定 (Implicit Binding)
当函数作为对象的方法被调用时,this 指向调用该方法的对象。
js
const user = {
name: 'fengfeng',
sayHi() {
console.log(this.name)
},
}
user.sayHi() // 'fengfeng'隐式丢失: 如果将对象方法赋值给一个变量,再调用该变量,会丢失绑定,回退到默认绑定。
js
const say = user.sayHi
say() // undefined (或全局 name)3. 显式绑定 (Explicit Binding)
使用 call, apply, bind 方法强制指定 this。
call(thisArg, ...args): 立即执行。apply(thisArg, [args]): 立即执行,参数为数组。bind(thisArg, ...args): 返回新函数,不立即执行。
js
function sayHi() {
console.log(this.name)
}
const obj = { name: 'Explicit' }
sayHi.call(obj) // 'Explicit'
sayHi.apply(obj) // 'Explicit'
const boundFn = sayHi.bind(obj)
boundFn() // 'Explicit'4. new 绑定 (New Binding)
使用 new 关键字调用构造函数时,this 指向新创建的实例对象。
js
function Person(name) {
this.name = name
}
const p = new Person('New Instance')
console.log(p.name) // 'New Instance'优先级
new 绑定 > 显式绑定 > 隐式绑定 > 默认绑定
- 函数是否在
new中调用?如果是,this是新创建的对象。 - 函数是否通过
call,apply,bind调用?如果是,this是指定的对象。 - 函数是否在某个上下文对象中调用(
obj.fn())?如果是,this是那个上下文对象。 - 如果都不是,使用默认绑定(全局对象或
undefined)。
特殊情况:箭头函数 (Arrow Function)
箭头函数没有自己的 this。 它的 this 是词法作用域决定的,即继承自外层函数(定义时所在的作用域)的 this。
特点:
call,apply,bind无法改变箭头函数的this。- 不能作为构造函数使用(不能
new)。
js
const obj = {
name: 'Obj',
// 普通函数
sayHi: function () {
setTimeout(function () {
console.log(this.name) // undefined (默认绑定,指向 window)
}, 100)
},
// 箭头函数
sayHiArrow: function () {
setTimeout(() => {
console.log(this.name) // 'Obj' (继承自 sayHiArrow 的 this)
}, 100)
},
}
obj.sayHi()
obj.sayHiArrow()面试题实战
js
var name = 'window'
const person = {
name: 'person',
say1: function () {
console.log(this.name)
},
say2: () => {
console.log(this.name)
},
say3: function () {
return function () {
console.log(this.name)
}
},
say4: function () {
return () => {
console.log(this.name)
}
},
}
person.say1() // 'person' (隐式绑定)
person.say2() // 'window' (箭头函数继承自全局)
person.say3()() // 'window' (独立调用,默认绑定)
person.say4()() // 'person' (箭头函数继承自 say4 的 this,即 person)