类式面向对象 vs 基于原型的面向对象

admin 发布于 2026-02-07 37 次阅读


AI 摘要

在面向对象编程(OOP)的世界里,类式和原型式代表了两种截然不同的对象创建与继承方式。类式面向对象以“类”为模板,强调通过类实例化对象;而原型式面向对象则直接通过对象继承对象,抛开类的概念。这篇文章通过对比这两种模型,深入探讨它们的底层逻辑,并揭示JavaScript中类的语法糖陷阱,挑战传统的编程认知。

之前学Python和JavaScript的时候,我就注意到一个问题,就是JavaScript能够直接在不定义类的情况下直接定义一个对象。

说来也有趣,我最开始接触的是Python,但在那里多修面向过程的思维,后来了解到JavaScript,才真正意义上理解了什么叫做面向对象。当时的理解就是以对象为基础,每个对象包含属性和方法,将有共同特征的对象抽象为类。而在实际编写代码的时候,编写一个类,通过类定义一个对象,通过操纵属性和方法的方式来实现功能。这些本是学JavaScript的时候深刻掌握的,但后来学到了JavaScript可以在不定一类的情况下定义对象。之前没有细想,只以为是JavaScript单独支持的一个功能。直到我意外的跟豆包聊天,才有了以下的知识点。

类式面向对象 vs 基于原型的面向对象

两者是实现面向对象的两种底层模型,核心差异在对象的创建方式和属性 / 方法的继承载体,最终都能实现封装、继承、多态,只是底层逻辑不同。

1. 类式面向对象(Class-based OOP)

核心:以类(Class) 为模板 / 蓝图,对象(实例)是类的实例化产物,继承是类与类之间的关系(子类继承父类)。逻辑:先定义类(规定属性和方法),再通过类创建对象,所有对象共享类的方法,属性是每个对象的独有数据。典型语言:Java、C++、Python、C#。

2. 基于原型的面向对象(Prototype-based OOP)核心:没有类的概念(ES6 的class是语法糖),直接创建对象,继承是对象与对象之间的关系(一个对象继承另一个对象,被继承的对象叫原型(Prototype))。逻辑:所有对象都是 “原型对象” 的副本,属性 / 方法通过原型链从原型对象继承,想创建相似对象,直接基于已有对象(原型)克隆即可。典型语言:JavaScript、Lua。

二、通俗对比(一句话理解)

类式:先画汽车设计图(类),再按设计图造具体的汽车(对象),所有同款式汽车的基础结构都来自设计图。原型:先造一辆基础汽车(原型对象),再以这辆车为模板复制 / 改造出其他汽车(新对象),新汽车直接继承基础汽车的零件(属性 / 方法)。

四、JavaScript 原型式的「语法糖陷阱」

很多人误以为 JS 是类式,因为 ES6 新增了class/extends,但这只是原型链的语法糖,底层依然是对象继承对象,没有真正的类。JS 原型式核心特征(对比 Python):ES5 无class,直接创建对象,通过Object.create(原型对象)实现继承;ES6 class A extends B,底层是A.prototype = Object.create(B.prototype),本质还是原型对象的继承;所有函数(包括构造函数)有prototype(原型对象),所有对象有__proto__,指向其原型对象,原型链就是__proto__的链式引用。ES6 class 底层原型链示例:

javascriptclass Phone { call() { console.log("打电话") } }
class SmartPhone extends Phone { surf() { console.log("上网") } }
const sp = new SmartPhone();
sp.call(); // 继承的方法// 底层还是原型链(类式语法糖的本质)
console.log(sp.__proto__ === SmartPhone.prototype); // trueconsole.log(SmartPhone.prototype.__proto__ === Phone.prototype); // true

如果去掉语法糖,ES5 直接用原型实现,更能体现本质

javascript// 原型对象
const PhoneProto = { call() { console.log("打电话") } };// 新对象继承原型对象
const p = Object.create(PhoneProto);
p.call(); // 继承原型的方法

六、关键结论

类式和原型式是OOP 的两种实现模型,无优劣,最终都能实现三大特性,只是底层逻辑不同;Python 是纯类式,类是原生核心概念,对象必须由类创建,继承是类级关系;JS 是纯原型式,ES6 的class只是语法糖,底层无类,一切围绕对象和原型链,继承是对象级关系;区分的关键:是否有「原生的、作为模板的类」 —— 有则是类式,无则是原型式。

说白了,我曾经的思维一直都是最经典的类式面向对象。究其本质, JavaScript甚至都没有类的概念。其所谓的class只是一个语法糖,他从一开始就是单独定义的每个对象,倒是倒反天刚了。

顺便补一句,跟我的一个朋友聊了聊这件事,他跟我说的另一个概念——继承。中心思想就是JavaScript的所有对象本质都是继承过来的。最基础的都是那个最根本的object。当时觉得挺有道理,但最后想了想他本身说的没错,但是继承跟对象创建的类又不是一回事。最简单的理解,继承可以看作是不同层级的关系,一种追根溯源的思想,而类强调的是将他们抽象共性,是同层级的关系,举例的话,继承就是动物和狗的关系,类就是猫和狗的关系。所以我又觉得他们两者不是一回事

但是写文章的时候,我又想到了一个逻辑,类本质是服务于创建对象,比如我定义了动物类就可以创建猫和狗这两个对象。其实我们也可以把类和对象看作两个层级,所以我的那位朋友说的也不无道理,但在逻辑上我通常不把类看作一个层级,或者说只有在继承的时候,我才会看类与类的层级。反正归根结底我看累的时候通常强调的是累,创建了有共性的对象,本质是在看对象的同一层级,当然我们也可以把类本身看作对象,看到了不同的层级继承关系。

说实话,我真没想到一个文章能扯这么多,从最开始了解编程知识,到最后逻辑的多次转折,算是启发思维了。

再引出一个小分支,未来我可能要写一篇关于编程对我个人思维影响的文章,嗯,非常合理 [旺柴]。

祝前程似锦

此作者没有提供个人介绍。
最后更新于 2026-02-11