
class 是 ES6 引入的语法糖,其本质是特殊类型的函数,不可被直接调用,仅支持 new 实例化;它自动绑定构造逻辑、隐式设置原型链,并强制执行严格模式,底层完全基于 JavaScript 原生的函数与原型机制实现。
`class` 是 es6 引入的语法糖,其本质是特殊类型的函数,不可被直接调用,仅支持 `new` 实例化;它自动绑定构造逻辑、隐式设置原型链,并强制执行严格模式,底层完全基于 javascript 原生的函数与原型机制实现。
在 JavaScript 中,class 并非面向对象语言中那种“全新类型”的类(如 Java 或 C++),而是一种高度封装的函数语法糖——它背后仍是函数对象,但行为受到严格约束与语义增强。
一、class 的本质:一个不可调用的、具有特殊内部属性的函数
当你声明:
class Hero {
constructor(name, level) {
this.name = name;
this.level = level;
}
greet() {
return `${this.name} says hello.`;
}
}
JavaScript 引擎实际创建的是一个具有 [[IsClassConstructor]]: true 内部标志的函数对象。可通过以下方式验证:
console.log(typeof Hero); // "function"
console.log(Hero.prototype); // { constructor: f, greet: f }
console.log(Hero.name); // "Hero"
console.log(Hero.prototype.constructor === Hero); // true
但它与普通函数的关键区别在于:
- ❌ 不能直接调用:
Hero('Alice', 10)会抛出TypeError: Class constructor Hero cannot be invoked without 'new'; - ✅ 只能通过
new调用:new Hero('Alice', 10)才合法; - ✅ 自动启用严格模式:无需
'use strict',constructor和所有方法体内默认处于严格模式; - ✅
constructor方法为必需:若省略,引擎自动插入空构造函数constructor() {}。
这解释了你最初的困惑:
“我们调用的是
Hero(类名),而非Hero.constructor”——没错,Hero本身即为构造器函数,而constructor只是该函数体内的一个命名方法定义,用于初始化实例属性。它不是独立函数,而是Hero函数执行时被调用的主体逻辑块。
二、class 的运行时行为:new 如何作用于类?
当执行 new Hero('Alice', 10) 时,引擎按如下步骤处理(与 MDN 描述一致,但适配类的语义):
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 创建空对象
newInstance; - 将
newInstance.[[Prototype]]指向Hero.prototype(而非Hero.prototype.prototype); -
以
newInstance为this,执行Hero函数体——注意:此时执行的正是constructor(name, level) { ... }内部代码,而非整个class块; - 若
constructor无显式返回对象,则自动返回newInstance。
因此,class Hero { constructor(...) { ... } } 等价于:
function Hero(name, level) {
if (typeof new.target === 'undefined') {
throw new TypeError('Class constructor Hero cannot be invoked without \'new\'');
}
this.name = name;
this.level = level;
}
Object.defineProperty(Hero, 'prototype', {
value: {
constructor: Hero,
greet() { return `${this.name} says hello.`; }
},
writable: false,
enumerable: false,
configurable: false
});
这就是“类是函数”的真正含义:它是一个带防护机制、自动挂载原型方法、且构造逻辑内聚的函数。
三、为什么 function fruit() { constructor(...) {...} } 不合法?
因为 constructor 在普通函数中只是一个普通标识符,不具任何特殊语义。上述写法等价于:
function fruit() {
const constructor = function(type) { this.type = type; };
}
它既不会被 new fruit() 调用,也不会影响实例初始化——fruit 函数体未对 this 赋值,返回的实例将为空对象 {}。
而 class Vegetable { constructor(type) { this.type = type; } } 中的 constructor 是类定义的保留成员名,由引擎识别并作为构造逻辑入口。
四、关键对比总结
| 特性 | 普通构造函数 | class |
|---|---|---|
| 调用方式 | 可 new Fn(),也可 Fn()(易误用) |
必须 new Class(),否则报错 |
| 方法挂载 | 需手动 Fn.prototype.method = ...
|
方法自动添加至 Class.prototype
|
| 构造逻辑 | 隐含在函数体中 | 显式声明为 constructor() 方法 |
| 严格模式 | 需手动加 'use strict'
|
自动启用 |
| Hoisting | 完全提升(可先调用后声明) |
仅声明提升,不可访问(TDZ):let/const 级提升 |
| 继承语法 |
Child.prototype = Object.create(Parent.prototype) + 手动修复 constructor
|
class Child extends Parent,简洁可靠 |
五、实践建议
- ✅ 优先使用
class:语义清晰、错误防护强、继承直观; - ⚠️ 理解其函数本质:调试时可用
console.log(Hero)查看其函数结构; - ? 避免混淆:
class不是“新对象模型”,它没有改变 JS 的原型继承本质,只是让原型操作更安全、更可读。
简言之:class 是 JavaScript 为构造函数披上的标准化外衣——它不改变底层规则,却极大提升了开发体验与代码健壮性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










