TypeScript、JavaScript、Java、Python、C++ 总览矩阵
跨语言比较最容易犯的错误是只对照语法。应按“类型系统—执行模型—内存与并发—生态用途”逐层比较。
1. 核心矩阵
| 维度 | TypeScript | JavaScript | Java | Python | C++ |
|---|---|---|---|---|---|
| 主要执行物 | 擦除/转换后的 JavaScript | JavaScript 源或引擎字节码/JIT | JVM 字节码(通常 JIT/AOT) | Python 源/字节码,由实现执行 | 通常 AOT 为本机码 |
| 类型检查 | 静态、渐进、结构化,允许有意不健全规则 | 运行时动态、弱类型转换 | 静态、以名义类型为主 | 运行时动态;类型提示通常由外部工具检查 | 静态、以名义类型和模板实例化为主 |
| 类型是否运行时存在 | 大多数类型擦除;类/enum 等值构造例外 | 值自带动态类别 | 类、数组等有运行时类型信息;泛型多数擦除 | 注解对象通常可在运行时读取,但不自动强制 | 类型决定布局与生成代码,RTTI 只覆盖部分多态信息 |
| 对象模型 | JavaScript 原型 + 静态结构类型 | 原型链、对象动态增删属性 | 类/接口、名义继承 | 对象/类动态模型、鸭子类型 | 值/引用/指针、类布局、继承 |
| 内存管理 | 由 JS host 垃圾回收 | 垃圾回收 | JVM 垃圾回收 | 实现相关;CPython 以引用计数加循环 GC 为主 | 自动存储期、RAII、智能指针,也可显式管理 |
| 泛型机制 | 类型参数通常擦除、结构化约束、条件/映射类型 | 无静态泛型 | 泛型多数擦除、边界与通配符 | typing 泛型供检查器;运行时模型动态 |
模板实例化,可生成不同本机代码 |
| 空值 | null/undefined,严格模式纳入联合 |
null/undefined |
引用可为 null,基础语言通常无完整非空类型 |
None |
指针可空;值对象本身不是空引用 |
| 异步主模型 | Promise、async/await、事件循环 | 同左 | 线程、Future、虚拟线程、结构化并发等 | asyncio、线程、进程,受实现影响 | 线程、future、协程、执行器生态 |
| 资源释放 | try/finally、显式资源管理协议、host API |
同左 | try-with-resources / GC | with 上下文管理器 |
析构与 RAII 确定性释放 |
| 典型优势 | Web/Node 全栈、库声明、强大类型运算 | 无构建即可运行、动态元编程、浏览器原生 | 大型服务、JVM 生态、强名义建模 | 脚本、数据、AI、快速迭代 | 系统、游戏、低延迟、硬件/内存控制 |
2. “相同写法”不等于“相同语义”
类
- TypeScript
class最终是 JavaScript 原型模型上的类语法。 - Java 类身份是名义的,接口需显式实现/继承关系。
- Python 类和属性高度动态。
- C++ 类还决定对象布局、构造析构、值复制/移动和 ABI。
泛型
- TypeScript 泛型表达静态关系,通常完全从 JS 输出消失。
- Java 泛型主要擦除,但检查基于名义类/接口,并存在通配符、桥接方法等 JVM 兼容机制。
- Python 类型提示不由运行时自动执行。
- C++ 模板通常按实参实例化,能影响二进制、性能和错误发生阶段。
异步
TypeScript/Python/Java/C++ 都可能写出 async 或 Future 风格代码,但其调度器、线程模型、取消语义和 I/O API 不同,不能仅凭关键字迁移设计。
3. 同一需求的最小表达
“返回列表第一项,不存在则空”:
function first<T>(items: readonly T[]): T | undefined {
return items[0]
}
function first(items) {
return items[0]
}
static <T> Optional<T> first(List<T> items) {
return items.isEmpty() ? Optional.empty() : Optional.of(items.getFirst());
}
from typing import TypeVar
T = TypeVar("T")
def first(items: list[T]) -> T | None:
return items[0] if items else None
#include <optional>
#include <vector>
template<class T>
std::optional<T> first(const std::vector<T>& items) {
if (items.empty()) return std::nullopt;
return items.front();
}
差异不仅是符号:JS 缺静态契约;TS 用 undefined;Java 使用名义泛型容器与 Optional;Python 提示不由运行时强制;C++ 返回值涉及值语义、复制/移动和模板实例化。
4. 迁移思维顺序
- 目标运行时如何加载模块、调度任务和管理内存?
- 类型在编译时、运行时分别存在多少?
- 错误通过异常、返回联合、错误码还是静态拒绝表达?
- 资源何时释放,是否确定性?
- 标准库和包管理边界是什么?
- 再迁移语法与框架。