创见博客
JavaScript的this(上下文对象)
七崽爱吃小饼干2026/01/21阅读 2专栏 JavaScript

一、this 是什么?

this 是 JavaScript 中的一个关键字,它不是固定不变的,而是在函数被调用时动态绑定的,指向的是当前函数执行时的上下文对象。

可以简单理解为:this 就是「谁调用了这个函数,this 就指向谁」

二、this 的绑定规则(核心)

this 的指向完全由函数的调用方式决定,不同调用方式对应不同的绑定规则,优先级从低到高依次是:

1. 默认绑定(全局/独立函数调用)

当函数以「独立函数」的形式调用时(没有任何对象前缀),this 会默认绑定到全局对象:

  • 浏览器环境:全局对象是 window;
  • Node.js 环境:全局对象是 global;
  • 严格模式(use strict):默认绑定失效,this 为 undefined。

示例代码:

javascript
// 浏览器环境下的示例
function sayHi() {
  console.log(this); // 非严格模式:window;严格模式:undefined
  console.log(this.name); // 非严格模式:'张三';严格模式:报错(Cannot read property 'name')
}

var name = '张三'; // 全局变量,挂载在 window 上
sayHi(); // 独立调用,触发默认绑定

2. 隐式绑定(对象方法调用)

当函数作为对象的方法被调用时,this 会指向这个调用函数的对象(即「点前面的对象」)。

示例代码:

javascript
const person = {
  name: '李四',
  sayHi: function() {
    console.log(this.name); // this 指向 person 对象,输出:李四
  }
};

person.sayHi(); // 函数作为 person 的方法调用,触发隐式绑定

// 注意:只看最后一层调用的对象
const outer = {
  name: '外层',
  inner: {
    name: '内层',
    sayHi: function() {
      console.log(this.name); // this 指向 inner,输出:内层
    }
  }
};
outer.inner.sayHi();

3. 显式绑定(强制指定 this)

通过 call()、apply()、bind() 方法,可以强制指定函数执行时的 this,这是最灵活的绑定方式。

方法语法特点
call()函数.call(this指向, 参数1, 参数2...)立即执行函数,参数逐个传递
apply()函数.apply(this指向, [参数1, 参数2...])立即执行函数,参数以数组形式传递
bind()函数.bind(this指向, 参数1, 参数2...)不立即执行,返回一个绑定了 this 的新函数

示例代码:

javascript
function sayHi(greet) {
  console.log(`${greet},我是${this.name}`);
}

const person = { name: '王五' };

// call 绑定:立即执行,参数逐个传
sayHi.call(person, '你好'); // 输出:你好,我是王五

// apply 绑定:立即执行,参数传数组
sayHi.apply(person, ['哈喽']); // 输出:哈喽,我是王五

// bind 绑定:返回新函数,需手动调用
const bindFn = sayHi.bind(person, '嗨');
bindFn(); // 输出:嗨,我是王五

4. new 绑定(构造函数调用)

当函数作为构造函数(通过 new 关键字调用)时,this 会指向新创建的实例对象。

示例代码:

javascript
function Person(name) {
  this.name = name; // this 指向 new 创建的实例
  this.sayHi = function() {
    console.log('我是' + this.name);
  };
}

const p1 = new Person('赵六');
p1.sayHi(); // this 指向 p1,输出:我是赵六

new 执行时的底层逻辑(帮助理解 this 指向):

  1. 创建一个空的新对象;
  2. 将新对象的 __proto__ 指向构造函数的 prototype;
  3. 将构造函数的 this 绑定到这个新对象;
  4. 执行构造函数的代码(给新对象添加属性/方法);
  5. 如果构造函数没有返回对象,就返回这个新对象。

5. 箭头函数的 this(特殊情况)

箭头函数没有自己的 this,它的 this 是继承自外层作用域的 this(词法作用域),且永远无法被修改(call/apply/bind 也没用)。

示例代码:

javascript
const person = {
  name: '钱七',
  normalFn: function() {
    console.log(this.name); // 隐式绑定,指向 person,输出:钱七
  },
  arrowFn: () => {
    console.log(this.name); // 继承外层全局的 this,浏览器中输出:undefined(无全局 name)
  }
};

person.normalFn();
person.arrowFn();

// 箭头函数的 this 无法被修改
person.arrowFn.call(person); // 依然输出 undefined

三、常见易混场景

1. 函数嵌套/回调函数中的 this

普通函数嵌套时,内层函数的 this 会丢失外层对象的绑定,默认指向全局(严格模式为 undefined):

javascript
const person = {
  name: '孙八',
  sayHi: function() {
    // 内层函数
    function innerFn() {
      console.log(this.name); // 默认绑定,输出:undefined(浏览器无全局 name)
    }
    innerFn();
  }
};
person.sayHi();

// 解决方法1:用变量保存外层 this
const person2 = {
  name: '孙八',
  sayHi: function() {
    const that = this; // 保存外层 this(指向 person2)
    function innerFn() {
      console.log(that.name); // 输出:孙八
    }
    innerFn();
  }
};

// 解决方法2:用箭头函数(继承外层 this)
const person3 = {
  name: '孙八',
  sayHi: function() {
    const innerFn = () => {
      console.log(this.name); // 继承 sayHi 的 this(指向 person3),输出:孙八
    };
    innerFn();
  }
};

2. DOM 事件中的 this

在 DOM 事件处理函数中,this 默认指向触发事件的 DOM 元素:

html
<button id="btn">点击</button>
<script>
const btn = document.getElementById('btn');
btn.onclick = function() {
  console.log(this); // 指向 btn 这个 DOM 元素
};
</script>

总结

  1. this 是动态绑定的,核心规则是「谁调用函数,this 就指向谁」,优先级:new 绑定 > 显式绑定(call/apply/bind) > 隐式绑定(对象方法) > 默认绑定(全局);
  2. 箭头函数没有自己的 this,它的 this 继承自外层作用域,且无法被修改(bind、call、apply);
  3. 解决嵌套函数 this 丢失的问题,可通过「保存外层 this(that/self)」或「使用箭头函数」。
评论
0/100