1183 字
6 分钟

this的指向,组件实例对象的创建方式,构造函数和实例对象的继承关系

欢迎来到我的博客!#

使用 Markdown 格式编写。

今天学到了什么#

  • this的指向
  • 组件实例对象的创建方式
  • 构造函数和实例对象的继承关系

this的指向#

“谁调用,这个函数里的 this 就是谁”这句话只在一种常见写法下成立:普通函数 + 以点调用形式执行。更准确的版本是:

  • 对“普通函数”(非箭头)来说,this 由“调用形式”决定,而不是由“函数写在哪”决定。

下面把最常见的几种“调用形式”列清楚,你就不会混了:

  • obj.fn()this === obj(这就是你说的“谁调用指向谁”最典型的情况)
  • fn()this === undefined(严格模式)/ window(非严格模式)
  • fn.call(x, ...) / fn.apply(x, ...)this === x
  • fn.bind(x):返回一个新函数,之后无论怎么调用,this 都固定是 x
  • new Fn()this 是新创建的实例对象
  • 箭头函数:没有自己的 thisthis 永远取决于“定义时外层的 this”(跟怎么调用无关)

结合你这行代码看:vue_test/10_src_组件自定义事件/App.vue

this.$refs.student.$on('atguigu', this.getStudentName)

这里其实出现了 3 个不同层面的“this”:

  • mounted() 里写的 this:是 App 实例(Vue 调用生命周期钩子时把 this 设成当前组件)
  • $on 这个方法执行时的 this:是 **this.refs.studentStudent实例),因为它是student.refs.student(Student 实例)**,因为它是 `student.on(…)` 这种点调用
  • 回调 this.getStudentNamethis 为什么还是 App:因为它是从 methods 里取出来的函数,Vue2 通常已经把它绑定到 App 上了(等价于你传了一个“已经 bind(App) 的函数”);所以后续触发事件时,就算内部想用 call/applythis,也改不掉

如果你把回调改成普通函数:

this.$refs.student.$on('atguigu', function () {
console.log(this)
})

那这时就更像你说的那套:触发时 Vue 会以某种形式调用它,this 往往会指向 Student(触发 $emit 的组件实例)

组件实例对象的创建方式#

new出来的也是实例对象,那我new出来demo之后,我再写呢?这是两个不同的Demo的实例对象吗?

对,是两个不同的实例对象(两个 vc),但它们来自同一个组件构造函数/组件定义

把概念拆开就清楚了:

1)Demo 是什么?#

const Demo = Vue.extend({...}) 得到的 Demo组件构造函数(可以理解成“类”)。

2)new Demo() 会得到什么?#

const d = new Demo() 得到的是一个组件实例对象(vc)
它只是在内存里创建了一个 Demo 实例,除非你 $mount 并插入 DOM,否则页面上未必有它。

3)<Demo /> 会得到什么?#

你在模板里写 <Demo />,Vue 在渲染时也会再创建一个 Demo 的组件实例对象(vc),并负责它的挂载、更新、销毁。

所以:

  • d = new Demo() 是你手动创建的 实例 A
  • 模板里的 <Demo /> 渲染出来的是 Vue 自动创建的 实例 B
  • A !== B,它们是两个不同对象,只是“同一个组件类型”的两个实例

它们会互相影响吗?#

默认不会(各自有自己的 data/生命周期/DOM)。
但如果你把它们都挂到页面、并且共享同一个外部对象(比如都引用了同一个全局变量/同一个 Vuex store/同一个单例对象),那表现上可能“看起来像联动”,本质是共享了外部状态,不是同一个实例。

构造函数和实例对象的继承关系#

实例对象不会继承构造函数身上的东西吗?

不会。实例对象不会“继承构造函数对象本身(静态属性)”上的东西,实例只会沿着它的原型链去找属性。

把关系画成一条链你就懂了:

  • 构造函数本身是一个对象:Vue
    你写 Vue.x = 123 是给这个“函数对象”加属性(静态属性)。
  • 实例对象是 new Vue() / 组件实例:vm
    vm 的原型链是:vm → Vue.prototype → Object.prototype ...

注意:原型链里有 Vue.prototype,没有 Vue 本身
所以:

  • Vue.prototype.x = 123vm.x 能找到(从原型上继承)
  • Vue.x = 123vm.x 找不到(因为 Vue 不在 vm 的原型链上)

一个最小原生 JS 例子(和 Vue 一样的规则):

function Foo() {}
Foo.a = 1 // 静态属性
Foo.prototype.b = 2 // 原型属性
const f = new Foo()
f.a // undefined
f.b // 2

如果你真的想让实例能访问到构造函数的静态属性,得自己“绕一下”,比如:

  • 在原型方法里用 this.constructor 去拿:this.constructor.a
  • 或者手动把 Foo.a 挂到 Foo.prototype

但在 Vue2 里,为了让组件里直接 this.$xxx 用,约定俗成就是挂 Vue.prototype.$xxx

赞助支持

如果这篇文章对你有帮助,欢迎赞助支持!

赞助
this的指向,组件实例对象的创建方式,构造函数和实例对象的继承关系
https://firefly.cuteleaf.cn/posts/study-everyday/2026-04-1今日学习-this详解组件实例对象的创建方式构造函数和实例对象的继承关系/
作者
LJC
发布于
2026-04-01
许可协议
CC BY-NC-SA 4.0
最后更新于 2026-04-01,距今已过 153 天

部分内容可能已过时

目录