Skip to content

this 指向

提示

this 关键字是 JavaScript 中最复杂的机制之一。它的指向完全取决于函数调用的位置(Call Site),而不是函数声明的位置。

核心规则:this 的四种绑定

判断 this 指向,主要看函数是如何被调用的。

1. 默认绑定 (Default Binding)

当函数独立调用(不带任何修饰符)时,this 指向全局对象。

  • 在浏览器中指向 window
  • 在 Node.js 中指向 global
  • 严格模式 ('use strict') 下,thisundefined
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 绑定 > 显式绑定 > 隐式绑定 > 默认绑定

  1. 函数是否在 new 中调用?如果是,this 是新创建的对象。
  2. 函数是否通过 call, apply, bind 调用?如果是,this 是指定的对象。
  3. 函数是否在某个上下文对象中调用(obj.fn())?如果是,this 是那个上下文对象。
  4. 如果都不是,使用默认绑定(全局对象或 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)

如有转载或 CV 的请标注本站原文地址