在前端世界里,关于 JavaScript 的一个老生常谈的问题是:
👉 它究竟是 面向对象语言,还是 基于对象语言?
有人说 JS 不算正统 OOP,因为直到 ES6 才有 class;
有人说 JS 是“基于对象”的,因为它允许运行时随意加属性。
可真相是:这两种说法都不完全对。
今天我就带你揭开 JavaScript 对象系统的底层秘密。
1. 面向对象 vs. 基于对象
JavaScript 标准本身其实用了两个词:
- 基于对象:语言和宿主的基础设施由对象来提供,JS 程序本质上就是一堆对象的集合。
- 面向对象:对象是抽象世界的一种自然映射,JS 也提供了面向对象编程的能力。
换句话说:
JavaScript 既是基于对象的运行时系统,又是支持面向对象编程范式的语言。
2. 对象的三大特征
不论哪种语言,对象都绕不开三大特征:
-
唯一标识性
即使两个对象长得一模一样,也绝不相等。var o1 = { a: 1 }; var o2 = { a: 1 }; console.log(o1 == o2); // false -
状态
对象在不同时间有不同状态,比如属性值会变化。 -
行为
对象的状态能因行为(方法调用)而改变。var o = { d: 1, f() { console.log(this.d); } }; o.f(); // 1
3. JavaScript 对象的“独门秘籍”:动态性
和 Java、C++ 不同,JS 对象是 高度动态的。
你可以在运行时随时给对象加属性:
var o = { a: 1 };
o.b = 2;
console.log(o.a, o.b); // 1 2
这让 JS 的对象系统极度灵活,同时也意味着:
👉 JS 可以在运行时模拟多数面向对象范式,而不仅仅是“类继承”。
4. 属性的两种形态
JS 属性远比你想象得复杂。分为两类:
-
数据属性(有
value、writable、enumerable、configurable)var o = { a: 1 }; Object.getOwnPropertyDescriptor(o, "a"); // { value: 1, writable: true, enumerable: true, configurable: true } -
访问器属性(通过 getter/setter 实现)
var o = { get a() { return 1; } }; console.log(o.a); // 1
这种设计让 JS 对象既能像字典,又能像函数工厂,抽象力直接拉满。
5. 为什么有人说 JS 不是 OOP?
原因在于:JS 的对象系统与主流基于类的 OOP 差异太大。
- Java 必须先定义类,再造对象;
- JS 可以直接定义对象,并在运行时扩展它。
但正是这种“反常规”的设计,让 JS 更加灵活。ES6 的 class 只是语法糖,本质上依旧是动态对象+原型链。
所以:
JavaScript 绝对是 OOP 语言,只不过它的 OOP 更自由、更动态。
写在最后
理解 JS 对象的关键是放下对“类”的执念。
- 对象 = 属性集合(键是字符串或 Symbol,值是数据属性或访问器属性)。
- JS 对象的运行时模型,足以模拟任意 OOP 范式。
- 灵活到爆炸,但也意味着容易“写出一坨屎山”。
互动问题:
👉 你更喜欢 严格的基于类 OOP(如 Java),还是 动态灵活的 JS OOP?
欢迎留言聊聊你的感受!