LOGO 首页 OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 技术文档 其他文档  
 
网站管理员

别再猜 this:先看它属于谁,再看它指向谁

freeflydom
2026年9月5日 8:45 本文热度 122

为什么要有 this

this 是 JavaScript 的关键字,用来隐式传递当前对象的引用。函数不必写死某个对象的名称,也不必额外接收对象参数,就能读取或修改调用者的数据。

这使函数只需要描述“做什么”,调用方式则决定“为谁执行”。同一个函数可以被不同对象复用,代码也因此更加简洁。

this 可以出现在哪

1. 全局作用域

在浏览器的普通脚本中,全局作用域里的 this 指向 window

console.log(this);
console.log(this === window); // true

2. 函数体内

普通函数中的 this 不是在函数定义时确定的,而是由函数的调用方式决定。同一个函数换一种调用方式,this 就可能发生变化。

因此,分析 this 时要始终抓住一句话:

先看这个 this 属于谁,再看它指向谁。

  • this 属于谁:先找到 this 写在哪里。普通函数有自己的 this;箭头函数没有自己的 this,需要继续向外寻找,直到找到最近的非箭头函数或全局作用域。
  • this 指向谁:找到真正拥有这个 this 的位置后,再结合调用方式判断。普通函数看它怎样被调用;全局作用域则直接根据运行环境判断。

全局作用域中的 this 可以直接判断;函数体内的 this 则需要结合下面的绑定规则分析。

this 的绑定规则

绑定规则解决的是第二步:已经知道 this 属于哪个函数后,再根据这个函数的调用形式判断 this 最终指向谁。

常见调用形式与绑定结果如下:

调用形式绑定规则this 的指向
foo()默认绑定window
obj.foo()隐式绑定obj
oo.foo.foo()多层调用离函数最近的调用对象
foo.call(obj) / foo.apply(obj) / foo.bind(obj)()显式绑定指定的 obj
new Foo()new 绑定新创建的实例

1. 默认绑定

函数以 foo() 的形式独立执行,并且 this 没有被显式绑定或 new 绑定改变时,会使用默认绑定。此时函数中的 this 指向 window

var a = 1;
function bar() {
    var a = 2;
    function foo() {
        console.log(this.a);
    }
    foo();
}
bar(); // 1

这段代码可以分三步判断:

  1. this 出现在 foo 中。
  2. foo() 是独立调用,使用默认绑定,所以 this 指向 window
  3. 浏览器普通脚本中,顶层通过 var 声明的 a 会成为 window.a,因此输出 1

bar 内部的 a 是局部变量。函数嵌套关系不会改变 foothis,所以这里不会输出 2

2. 隐式绑定

当函数保存在对象属性中,并通过这个对象调用时,函数中的 this 指向该对象。

function foo() {
    console.log(this.a);
}
var obj = {
    a: 1,
    foo: foo
};
obj.foo(); // 1

对象属性 foo 保存的是函数引用。真正决定 this 的是调用表达式 obj.foo():调用点前有 obj,所以 foo 中的 this 指向 obj,最终读取到 obj.a

如果同一个函数由另一个对象调用,this 也会随之改变:

var another = {
    a: 2,
    foo: foo
};
another.foo(); // 2

这正是 this 便于复用的原因:函数本身没有改变,调用者决定了它操作哪个对象。

3. 隐式丢失:多层对象调用

多层对象调用不会把最外层对象一直传递给函数。判断时只看最终调用点,this 指向离函数最近的调用对象。

function foo() {
    console.log(this.a);
}
var obj = {
    a: 1,
    foo: foo
};
var oo = {
    a: 2,
    foo: obj
};
oo.foo.foo(); // 1

oo.foo 的值是 obj,所以 oo.foo.foo() 可以看成由 obj 调用 foo。直接调用者是 obj,而不是最外层的 oo,因此 this.a 的结果是 1

4. 显式绑定

不想由调用形式自动判断时,可以使用 callapplybind 直接指定函数中的 this

function foo(x, y) {
    console.log(this.a, x + y);
}
var GGbond = { a: 1 };
var FF = { a: 2 };
var CRQ = { a: 3 };
foo.call(GGbond, 1, 2); // 1 3
foo.apply(FF, [2, 3]);  // 2 5
const bar = foo.bind(CRQ, 3, 4);
bar(); // 3 7

三种方法都能指定 this,区别在于调用时机和参数形式:

  • call 立即调用函数,从第二个参数开始逐个传递实参。
  • apply 立即调用函数,使用数组传递实参。
  • bind 不会立即调用,而是返回一个绑定好 this 的新函数,需要再次调用。

5. new 绑定

函数通过 new 调用时,其中的 this 指向新创建的实例对象。构造函数中通过 this 添加的属性,也会出现在这个实例上。

function Person() {
    this.name = "GGBond";
}
const p = new Person();
console.log(p.name); // GGBond

调用 new Person() 时,Person 中的 this 指向实例 p,所以 this.name = "GGBond" 等同于给 p 添加 name 属性。

箭头函数

箭头函数没有自己的 this,也不使用普通函数的绑定规则。它会沿用定义位置外层作用域中的 this;当箭头函数写在普通函数内部时,它会沿用该普通函数的 this

function foo() {
    var fn = () => {
        this.a = 2;
    };
    fn();
}
var obj = {
    a: 1,
    bar: foo
};
obj.bar();
console.log(obj.a); // 2

这段代码的执行过程是:

  1. obj.bar() 调用普通函数 foo,所以 foothis 指向 obj
  2. 箭头函数 fn 没有自己的 this,于是沿用 foothis
  3. this.a = 2 实际修改的是 obj.a,最终输出 2

箭头函数不能作为构造函数,因此不能通过 new 调用。

普通函数的 this 取决于调用方式;箭头函数的 this 取决于定义位置的外层作用域。抓住这一区别,就能快速判断代码中的 this 指向。

阅读原文:点击这里


该文章在 2026/9/5 8:45:24 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved  粤ICP备13012886号-2  粤公网安备44030602007207号