一个功能完善的 JavaScript 解释器实现,用于深入理解编程语言的词法分析、语法解析和运行时执行原理。
🧠 本项目不仅实现了 JavaScript 的核心特性,还包括 ES6+ 的现代语法支持,如箭头函数、解构赋值、类、Promise 等高级功能。
- 基本类型:Number、String、Boolean、null、undefined、NaN、Infinity
- 复合类型:Object、Array、Function、Class
- ES6 集合:Set、Map(完整实现,支持 add、delete、has、clear、forEach 等方法)
- let:块级作用域变量
- const:常量声明,不可重新赋值
- var:函数作用域变量
- 暂时性死区(TDZ):正确处理变量声明前访问
- 块级作用域:支持 if、for、while 等语句的块级作用域
- 算术运算符:
+、-、*、/、% - 比较运算符:
==、===、!=、!==、<、>、<=、>= - 逻辑运算符:
&&、||、! - 位运算符:
&、|、^、~、<<、>>、>>> - 赋值运算符:
=、+=、-=、*=、/= - 一元运算符:
++、--、+、-、!、typeof、void、delete - 三元运算符:
? : - 逗号运算符:
, - 成员运算符:
in、instanceof - 展开运算符:
...(在数组、函数参数中)
- 条件语句:if/else、switch/case/default
- 循环语句:for、while、do-while、for...in、for...of
- 跳转语句:break、continue、return
- 函数声明:
function name() {} - 函数表达式:
const fn = function() {} - 箭头函数:
(param) => { return value; } - 默认参数:
function fn(a = 1, b = 2) {} - 剩余参数:
function fn(...args) {} - 闭包:完整的词法作用域支持
- 高阶函数:函数作为参数和返回值
- 递归优化:尾递归检测和优化
- 类声明:
class ClassName {} - 构造函数:
constructor() {} - 实例方法:
methodName() {} - 静态方法:
static methodName() {} - Getter/Setter:
get prop() {}/set prop(value) {} - 类继承:
class Child extends Parent {} - super 调用:
super()和super.method() - instanceof 检测:完整的原型链支持
- 数组解构:
- 基本解构:
let [a, b, c] = [1, 2, 3] - 默认值:
let [a = 1, b = 2] = [] - 嵌套解构:
let [a, [b, c]] = [1, [2, 3]] - 剩余模式:
let [a, ...rest] = [1, 2, 3, 4] - 跳过元素:
let [a, , b] = [1, 2, 3]
- 基本解构:
- 对象解构:
- 基本解构:
let {a, b} = {a: 1, b: 2} - 重命名:
let {a: x, b: y} = {a: 1, b: 2} - 默认值:
let {a = 1, b = 2} = {} - 嵌套解构:
let {a, b: {c, d}} = {a: 1, b: {c: 2, d: 3}} - 剩余属性:
let {a, ...rest} = {a: 1, b: 2, c: 3}
- 基本解构:
- Promise:完整实现
new Promise((resolve, reject) => {})promise.then(onFulfilled, onRejected)promise.catch(onRejected)promise.finally(onFinally)Promise.resolve(value)Promise.reject(reason)Promise.all(iterable)Promise.race(iterable)
- 异常捕获:try/catch/finally 完整支持
- 错误类型:ReferenceError、TypeError、RangeError、SyntaxError
- 自定义错误:
throw new Error(message) - 错误传播:正确的错误冒泡机制
- 作用域链:正确的词法作用域和作用域链查找
- 变量提升:模拟 JavaScript 的变量提升行为
- 闭包机制:捕获外部变量,支持多层嵌套
- 原型继承:完整的原型链支持
- this 绑定:正确处理方法调用中的 this
- 内置对象:Math、JSON、Array、String、Object 等
- 沙箱限制:调用栈深度限制、执行时间限制、循环次数限制
项目包含 14 个测试套件,超过 400+ 测试用例,全面验证功能正确性:
- ✅ variables.test.js (83 行) - 变量声明、类型、赋值操作符
- ✅ constants.test.js - const 声明和不可变性
- ✅ operators.test.js (480 行) - 一元、位运算、逻辑、比较运算符
- ✅ comments.test.js - 单行、多行注释处理
- ✅ control-flow.test.js - if/else、switch、三元运算符
- ✅ scope.test.js - 作用域链、块级作用域、闭包
- ✅ functions.test.js (54 行) - 函数声明、表达式、高阶函数
- ✅ advanced-features.test.js (429 行) - 闭包、箭头函数、默认参数、剩余参数
- ✅ class.test.js (401 行) - 类、继承、静态方法、getter/setter
- ✅ data-structures.test.js - 数组、对象字面量、属性访问
- ✅ collections.test.js (536 行) - Set 和 Map 完整实现
- ✅ destructuring.test.js (277 行) - 数组和对象解构赋值
- ✅ promise.test.js (299 行) - Promise 完整实现
- ✅ exceptions.test.js - try/catch/finally、错误类型
在浏览器中打开项目根目录的 index.html 即可访问 TinyJS 网站:
- 🏠 宣传页:
index.html- 项目介绍和特性展示 - 🎯 演练场:
playground.html- 交互式代码测试平台
演练场功能:
- ✅ 96+ 代码示例,涵盖所有语法特性(从测试用例自动同步)
- ✅ 7 大分类、23 个子分类,系统化学习路径
- ✅ Monaco 编辑器,VS Code 同款体验
- ✅ 实时运行代码,查看结果和控制台输出
- ✅ 浅色/暗色主题切换
- ✅ 代码搜索和分类浏览
- ✅ 快捷键支持(Cmd/Ctrl + Enter 运行)
- ✅ 示例与测试同步,保证代码正确性
# 克隆仓库
git clone https://github.com/leyen-me/tinyjs.git
cd tinyjs
# 安装依赖
npm install
# 或
pnpm install
# 运行测试
npm test
# 运行特定测试文件
npm test -- class.test.js
# 查看测试覆盖率
npm run test:coverage
# 打开网站(使用任意 HTTP 服务器)
python3 -m http.server 8000
# 然后访问 http://localhost:8000import { run } from './src/main.js';
// 基本运算
const result1 = run(`
let a = 10;
let b = 20;
a + b
`);
console.log(result1); // 30
// 函数和闭包
const result2 = run(`
function createCounter() {
let count = 0;
return function() {
count = count + 1;
return count;
};
}
const counter = createCounter();
counter(); // 1
counter(); // 2
counter() // 3
`);
console.log(result2); // 3run(`
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return this.name + " makes a sound";
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
speak() {
return this.name + " barks";
}
}
const dog = new Dog("Buddy", "Labrador");
console.log(dog.speak()); // "Buddy barks"
`);run(`
let result;
Promise.resolve(10)
.then(x => x * 2)
.then(x => x + 5)
.then(x => { result = x; });
console.log(result); // 25
`);run(`
// 数组解构
let [a, b, ...rest] = [1, 2, 3, 4, 5];
console.log(a, b, rest); // 1, 2, [3, 4, 5]
// 对象解构
let {name, age, ...others} = {name: "Alice", age: 25, city: "NY", job: "Engineer"};
console.log(name, age, others); // "Alice", 25, {city: "NY", job: "Engineer"}
`);run(`
// Set 集合
let s = new Set([1, 2, 3, 2, 1]);
s.add(4);
console.log(s.size); // 4
console.log(s.has(2)); // true
// Map 映射
let m = new Map();
m.set("key1", "value1");
m.set("key2", "value2");
console.log(m.get("key1")); // "value1"
console.log(m.size); // 2
`);为了确保 Playground 中展示的示例代码始终正确且与测试用例保持同步,我们建立了一套自动化的同步机制:
测试用例文件 (test/*.test.js)
↓
提取脚本 (scripts/extract-examples.js)
↓
示例数据 (assets/js/examples.js)
↓
Playground UI (playground.html)
- ✅ 质量保证:所有示例均基于通过的测试用例
- ✅ 自动同步:测试更新后可自动重新生成示例
- ✅ 全面覆盖:从 293 个测试用例中精选 96 个代表性示例
- ✅ 分类清晰:7 大类 23 个子类,系统化组织
- ✅ 可追溯性:每个示例都关联到源测试用例
| 一级分类 | 二级分类数 | 示例数 | 覆盖内容 |
|---|---|---|---|
| 基础语法 | 3 | 17 | 变量、常量、运算符 |
| 控制流 | 4 | 14 | 条件、循环、作用域 |
| 函数 | 3 | 7 | 声明、箭头、参数 |
| 面向对象 | 3 | 9 | 类、继承、访问器 |
| 数据结构 | 5 | 25 | 数组、对象、集合、解构 |
| 异步与错误 | 2 | 10 | Promise、异常处理 |
| 高级特性 | 3 | 7 | 闭包、高阶、柯里化 |
| 总计 | 23 | 96 | 完整语法覆盖 |
# 重新生成 Playground 示例
node scripts/extract-examples.js
# 输出示例:
# ✅ examples.js 已生成
# 📊 统计信息:
# - 一级分类: 7 个
# - 二级分类: 23 个
# - 示例总数: 96 个
# - 覆盖率提升: 从 38 个增加到 96 个 (153% 增长)详细说明请参考 EXAMPLES_SYNC.md 文档。
-
词法分析器(Lexer)
- 正则表达式 tokenization
- 关键字、操作符、标识符识别
- 注释过滤(单行
//和多行/* */)
-
语法分析器(Parser)
- 递归下降分析(Recursive Descent Parsing)
- 抽象语法树(AST)构建
- 运算符优先级处理
- 语句与表达式解析
-
执行引擎(Evaluator)
- AST 遍历执行
- 环境对象管理(Environment)
- 作用域链实现
- 闭包支持
-
作用域管理
Environment基类:基础环境BlockEnvironment:块级作用域FunctionEnvironment:函数作用域- 变量查找缓存优化
-
错误处理
- 自定义错误类型
- 异常传播机制
- 调用栈管理
-
性能优化
- 尾递归优化(TCO)
- 调用栈深度限制
- 循环计数器
- 执行时间监控
// AST 节点类型(部分)
- Literal // 字面量
- Identifier // 标识符
- BinaryExpression // 二元表达式
- UnaryExpression // 一元表达式
- AssignmentExpression // 赋值表达式
- UpdateExpression // 更新表达式 (++/--)
- CallExpression // 函数调用
- MemberExpression // 成员访问
- ArrayExpression // 数组字面量
- ObjectExpression // 对象字面量
- FunctionExpression // 函数表达式
- ArrowFunctionExpression // 箭头函数
- ClassExpression // 类表达式
- ConditionalExpression // 三元表达式
- SequenceExpression // 逗号表达式
- ArrayPattern // 数组解构模式
- ObjectPattern // 对象解构模式
- RestElement // 剩余元素
- SpreadElement // 展开元素本项目适合作为以下学习场景的参考:
- 词法分析(Tokenization)实现
- 语法分析(Parsing)策略
- AST 设计与遍历
- 运算符优先级处理
- 环境对象模式(Environment Pattern)
- 访问者模式(Visitor Pattern)
- 作用域链实现
- 闭包机制
- 变量提升(Hoisting)
- 执行上下文(Execution Context)
- 原型链继承
- this 绑定机制
- 箭头函数实现
- 解构赋值算法
- Promise 异步机制
- Class 类语法糖
// 默认限制
const SANDBOX_LIMITS = {
maxCallStackDepth: 1000, // 最大调用栈深度
maxExecutionTime: 5000, // 最大执行时间(5秒)
maxLoopIterations: 1000000 // 最大循环次数
};- ✅ 尾递归优化(Tail Call Optimization)
- ✅ 变量查找缓存
- ✅ 调用栈管理
- ✅ 循环监控
⚠️ 不支持实际的异步执行(Promise 是同步模拟)⚠️ 没有实现 async/await 语法⚠️ 不支持 ES Modules 的 import/export⚠️ 没有实现所有内置 API(仅支持常用的)
代码统计:
- src/main.js: ~3500 行
- 测试文件: 14 个
- 测试用例: 400+ 个
- 测试代码: ~3000 行
功能覆盖:
- 基础语法: ✅ 100%
- 控制流: ✅ 100%
- 函数特性: ✅ 100%
- 面向对象: ✅ 100%
- ES6+ 特性: ✅ 90%
- 异步编程: ✅ 80% (同步模拟)
欢迎提交 issue 和 pull request!
- ✨ 添加更多 JavaScript 特性(如 async/await、生成器等)
- ⚡ 性能优化(词法分析、执行引擎)
- 🐛 修复 bug 和边界情况
- 📝 完善文档和注释
- ✅ 增加测试用例
# 1. Fork 并克隆项目
git clone https://github.com/leyen-me/tinyjs.git
# 2. 创建功能分支
git checkout -b feature/your-feature-name
# 3. 开发并测试
npm test
# 4. 提交代码
git commit -m "feat: add your feature"
# 5. 推送分支
git push origin feature/your-feature-name
# 6. 提交 Pull Request- 遵循现有代码风格
- 添加必要的注释(尤其是复杂逻辑)
- 每个新功能必须有对应测试用例
- 确保所有测试通过
- Crafting Interpreters - 解释器实现经典书籍
- The Super Tiny Compiler - 简单的编译器实现
- Acorn - JavaScript 解析器
- Babel Parser - Babel 的解析器
- JS-Interpreter - Google 的 JavaScript 解释器
- QuickJS - 轻量级 JavaScript 引擎
A: 本项目是一个同步解释器,没有实现事件循环和异步队列。Promise 只是模拟了 API,实际上是立即执行的。
A: 本项目的目标是教学和学习,不是完整的 JavaScript 引擎。我们优先实现最核心的特性以保持代码的可读性。
A: 可以在 src/main.js 中添加 console.log,或者使用 Node.js 调试器:
node --inspect-brk node_modules/.bin/jest --runInBandA: 作为教学项目,性能不是首要目标。但我们实现了尾递归优化和变量缓存等优化手段。
MIT License. 详见 LICENSE 文件。
- 作者:Leyen Me
- 邮箱:672228275@qq.com
- GitHub Issues:https://github.com/leyen-me/tinyjs/issues
如有问题或建议,欢迎通过以上方式联系或提交 GitHub Issue!
如果这个项目对你有帮助,请给个 Star ⭐ 支持一下!