深入理解JavaScript类中公共实例字段与原型链

酷敏大大_6168

酷敏大大_6168

2025-09-26

391人浏览

原创

深入理解javascript类中公共实例字段与原型链

本文深入探讨JavaScript类中公共实例字段与原型链的关系。揭示了与方法不同,公共实例字段并非定义在类的原型上,而是直接在每个类实例创建时通过构造函数赋值,成为实例独有的属性。这有助于理解ES6类在底层如何处理不同类型的成员,并避免在访问这些属性时产生混淆。

JavaScript类与原型链的基础

在JavaScript中,ES6的class语法实际上是基于其现有的原型继承机制提供的一种语法糖。这意味着,虽然我们使用更简洁的面向对象语法,但其底层仍然是基于函数和原型链来构建的。对于类中定义的方法,这一机制表现得尤为明显。

考虑以下类的定义:

class Foo {
  // 这是一个方法
  greet() {
    console.log("Hello from Foo!");
  }
}

当我们定义一个方法greet()时,它会被放置在Foo构造函数的原型对象(即Foo.prototype)上。这使得所有Foo的实例都能通过原型链访问到这个方法,并且这些实例共享同一个方法定义,从而节省内存。在底层,这等同于:

function Foo() {}
Foo.prototype.greet = function() {
  console.log("Hello from Foo!");
};

我们可以通过Foo.prototype.greet直接访问到这个方法:

console.log(typeof Foo.prototype.greet); // function

公共实例字段的特殊性

然而,当我们在类中定义公共实例字段(Public Instance Fields)时,其行为与方法有所不同。公共实例字段是一种在类体中直接声明并赋值的属性,例如:

class Bar {
  // 这是一个公共实例字段
  message = "Hello World";
}

与方法不同,这个message属性并不会被添加到Bar.prototype上。如果你尝试访问Bar.prototype.message,你会发现它是undefined:

console.log(Bar.prototype.message); // undefined

那么,这个message属性究竟存放在哪里呢?

实例字段的内部机制

公共实例字段的真正位置在于每个通过new关键字创建的类实例上。当一个类的实例被创建时,JavaScript引擎会在其内部构造过程中,将这些公共实例字段直接赋值给新创建的实例对象。

java-api-doc-generator
java-api-doc-generator

分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。

下载

这实际上等同于在类的constructor方法中,使用this关键字为实例添加属性:

class BarEquivalent {
  constructor() {
    this.message = "Hello World"; // 在构造函数中为实例赋值
  }
}

因此,每个Bar或BarEquivalent的实例都会拥有自己独立的message属性副本。

const instance1 = new Bar();
const instance2 = new Bar();

console.log(instance1.message); // "Hello World"
console.log(instance2.message); // "Hello World"

// 它们是各自实例的属性
console.log(instance1.hasOwnProperty('message')); // true
console.log(Bar.prototype.hasOwnProperty('message')); // false

这意味着,message属性是instance1和instance2各自独有的,而不是通过原型链继承而来。

示例与对比

为了更清晰地展示方法和公共实例字段的区别,我们来看一个综合示例:

class MyClass {
  // 公共实例字段
  instanceProperty = "我是实例属性";

  // 方法
  greet() {
    console.log("Hello from method!");
  }

  // 另一个方法,访问实例属性
  displayInstanceProperty() {
    console.log(`实例属性的值是: ${this.instanceProperty}`);
  }
}

// 创建一个实例
const myInstance = new MyClass();

// 1. 访问方法
console.log("--- 访问方法 ---");
console.log(typeof MyClass.prototype.greet); // function
myInstance.greet(); // Hello from method!

// 2. 访问公共实例字段
console.log("\n--- 访问公共实例字段 ---");
console.log(MyClass.prototype.instanceProperty); // undefined (不在原型上)
console.log(myInstance.instanceProperty); // 我是实例属性 (在实例上)

// 3. 方法可以访问实例属性
myInstance.displayInstanceProperty(); // 实例属性的值是: 我是实例属性

// 4. 验证属性归属
console.log("\n--- 属性归属验证 ---");
console.log(myInstance.hasOwnProperty('instanceProperty')); // true
console.log(MyClass.prototype.hasOwnProperty('greet')); // true
console.log(Object.getOwnPropertyDescriptor(MyClass.prototype, 'greet')); // { value: [Function: greet], writable: true, enumerable: false, configurable: true }
console.log(Object.getOwnPropertyDescriptor(myInstance, 'instanceProperty')); // { value: '我是实例属性', writable: true, enumerable: true, configurable: true }

从上述示例中,我们可以清楚地看到:

  • greet方法存在于MyClass.prototype上,并且实例通过原型链访问它。
  • instanceProperty字段直接存在于myInstance对象上,而不是MyClass.prototype上。

注意事项与总结

  1. 内存与性能: 由于公共实例字段是直接添加到每个实例上的,如果一个类有大量实例且每个实例都有大量实例字段,可能会比将所有成员都放在原型上消耗更多的内存。然而,对于大多数实际应用场景,这种差异通常可以忽略不计。
  2. 继承行为: 当子类继承父类时,父类的公共实例字段会通过调用父类的构造函数(super())被添加到子类实例上。
  3. 何时使用: 当你需要每个实例拥有自己独立的数据副本时,公共实例字段是理想的选择。例如,每个用户实例有自己的用户名、邮箱等。当所有实例共享相同的行为或常量时,方法和静态属性更合适。

理解公共实例字段与原型链之间的这种区别,对于深入掌握JavaScript的面向对象编程至关重要。它帮助我们更准确地预测代码行为,并编写出更健壮、更易于维护的JavaScript类。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关专题

更多
es6新特性
es6新特性

es6新特性有:1、块级作用域变量;2、箭头函数;3、模板字符串;4、解构赋值;5、默认参数;6、 扩展运算符;7、 类和继承;8、Promise。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.17

285

5

es6新特性有哪些
es6新特性有哪些

es6的新特性有:1、块级作用域;2、箭头函数;3、解构赋值;4、默认参数;5、扩展运算符;6、模板字符串;7、类和模块;8、迭代器和生成器;9、Promise对象;10、模块化导入和导出等等。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.04

406

5

JavaScript ES6新特性
JavaScript ES6新特性

ES6是JavaScript的根本性升级,引入let/const实现块级作用域、箭头函数解决this绑定问题、解构赋值与模板字符串简化数据处理、对象简写与模块化提升代码可读性与组织性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2025.12.24

375

12

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

2023.10.24

6184

49

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

2025.09.05

6955

14

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

2025.11.27

362

13

C++ 面向对象编程与设计模式实践
C++ 面向对象编程与设计模式实践

本专题整合了 C++ 面向对象编程的核心机制,涵盖类的定义与访问控制、构造函数与析构函数、拷贝语义与移动语义、继承与虚函数多态、抽象类与接口、运算符重载、友元函数等关键知识点,同时结合单例模式、工厂模式、观察者模式、策略模式等常用设计模式的 C++ 实现,帮助开发者写出结构清晰、易于维护的面向对象代码。

2026.04.09

364

30

Java 面向对象与核心编程机制
Java 面向对象与核心编程机制

系统讲解 Java 面向对象编程的核心知识体系,涵盖类的定义与封装、构造方法与 this/super 关键字、继承与方法重写、多态与向上向下转型、抽象类与接口的区别与设计原则、异常处理机制(try-catch-finally / 自定义异常)、泛型的类型参数与通配符、集合框架(List/Set/Map)的使用与遍历方式,帮助开发者全面掌握 Java 程序设计的核心机制与面向对象思维。

2026.04.17

243

15

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

2025.09.05

6955

14

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WebStorm 官方调试文档
WebStorm 官方调试文档

共0课时 | 0人学习

React 教程
React 教程

共58课时 | 12.3万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 6.7万人学习