构造函数执行时内存分配分阶段完成:先分配对象内存并绑定this,再初始化成员。this指向已分配但未初始化的内存,此时对象处于“半构建”状态,各语言对初始化顺序和this可用性有不同约束。

构造函数执行时,内存分配是分阶段完成的,不是一步到位。核心在于:对象内存先分配,this才被绑定,之后才是成员初始化。
内存分配发生在构造函数调用之前
当使用 new(JavaScript)、new 表达式(Java)或直接声明(C++ 栈对象)时,运行时首先为对象分配一块连续内存空间——这块空间大小由类/构造函数定义的成员变量决定。此时对象“存在”,但内容未初始化,this 指向的就是这块刚分配好的内存地址。
- JavaScript 中,
new Person()会先在堆上分配内存,再把该地址作为 this 传入构造函数 - Java 中,
new Person()同样先在堆分配,然后调用构造器;父类构造器执行前,子类字段内存已预留 - C++ 中,栈上局部对象或堆上
new对象都先完成内存布局,再进入构造函数体
初始化顺序影响 this 的可用性
this 虽然从一开始就有值,但它所指的对象处于“半构建”状态:部分成员可能还没初始化,尤其是依赖初始化列表或父类构造的场景。
- C++ 中,初始化列表(如
: name(val), age(0))在构造函数体执行前运行,此时 this 已有效,但不能调用虚函数——因为虚表可能尚未设置完毕 - Java 中,父类构造器必须最先执行,子类字段在此时尚未赋值(默认为 0、null 或 false),此时若通过 this 调用被子类重写的方法,可能访问到未初始化的字段
- JavaScript 中,this 在构造函数体内完全可用,但若在构造过程中同步调用异步方法或回调,需注意此时对象可能还未赋完所有属性
方法与属性的内存归属不同
构造函数内通过 this.xxx = ... 设置的属性,存储在当前对象的堆内存中,每个实例独享一份;而方法通常不重复拷贝,而是挂载在原型(JS)或类结构(Java/C++)上,多个实例共享同一份代码内存。
- JS 中
this.sayHello = function(){...}会在每个实例上新建函数对象,浪费内存;推荐定义在Person.prototype.sayHello - Java/C++ 中,非静态方法天然共享,this 只是隐式传入的当前实例指针,不参与方法体的内存分配
- 属性值如果是引用类型(如数组、对象),this.prop = {...} 分配的是新对象内存,而 this.prop = existingObj 只复制引用地址
不显式写 this 也不等于没用它
即使代码里没出现 this 关键字,只要访问了实例成员,编译器或解释器都会自动补上前缀。
- Java 中写
setName("Alice"),等价于this.setName("Alice") - JS 中
getName()在构造函数内调用,实际是this.getName(),前提是该方法存在于原型链上 - 这意味着:构造函数里任何对实例字段或方法的读写,底层都依赖 this 所指向的那块内存地址











