1. JavaScript基础概览:从历史到现代应用
JavaScript诞生于1995年,由网景公司的Brendan Eich在短短10天内设计完成。这门语言最初被命名为LiveScript,后来为了蹭当时Java的热度才改名为JavaScript——尽管两者在语法特性上相似,但本质完全不同。作为前端开发的三大基石之一(HTML、CSS、JavaScript),现代JavaScript已经发展成一门能够处理复杂业务逻辑的全栈语言。
提示:虽然JavaScript和Java名称相似,但它们是两种完全不同的语言。Java需要编译后运行,而JavaScript是解释型语言,由浏览器直接执行。
在浏览器环境中,JavaScript通过DOM(文档对象模型)与页面交互。比如下面这段代码可以修改网页标题:
document.title = "新标题";而在Node.js环境下,JavaScript可以像Python一样进行文件操作:
const fs = require('fs'); fs.readFile('example.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); });1.1 数据类型与变量声明
JavaScript有7种原始数据类型:
- Boolean:true/false
- Null:表示空值
- Undefined:未定义
- Number:整数和浮点数
- BigInt:大整数
- String:字符串
- Symbol:唯一标识符
以及1种复杂类型:
- Object:对象
变量声明有三种方式:
var name = "老式声明"; // 函数作用域 let age = 25; // 块级作用域 const PI = 3.14; // 常量注意:现代开发中应该避免使用var,优先使用const,需要重新赋值时才用let。const声明的数组和对象虽然不能重新赋值,但其内容是可以修改的。
1.2 类型转换的陷阱
JavaScript是弱类型语言,类型转换常常让新手困惑:
console.log(1 + "1"); // "11" (字符串拼接) console.log("2" * "3"); // 6 (自动转为数字) console.log([] == ![]); // true (抽象相等比较的奇怪结果)建议总是使用严格相等比较:
console.log(0 === false); // false console.log(null === undefined); // false2. 函数与作用域深度解析
2.1 函数的多种定义方式
函数声明:
function greet(name) { return `Hello, ${name}!`; }函数表达式:
const greet = function(name) { return `Hello, ${name}!`; };箭头函数(ES6):
const greet = (name) => `Hello, ${name}!`;立即执行函数(IIFE):
(function() { console.log("立即执行"); })();2.2 作用域与闭包
JavaScript采用词法作用域(静态作用域),函数在定义时就确定了作用域链:
function outer() { const x = 10; function inner() { console.log(x); // 可以访问外部变量 } return inner; } const closure = outer(); closure(); // 输出10闭包的实际应用——创建私有变量:
function createCounter() { let count = 0; return { increment() { count++; }, getCount() { return count; } }; } const counter = createCounter(); counter.increment(); console.log(counter.getCount()); // 1 console.log(counter.count); // undefined (无法直接访问)2.3 this关键字的迷思
this的值取决于函数的调用方式:
const obj = { name: "Alice", greet: function() { console.log(`Hello, ${this.name}`); } }; obj.greet(); // "Hello, Alice" (方法调用) const greetFunc = obj.greet; greetFunc(); // "Hello, undefined" (函数调用) // 使用bind固定this const boundGreet = obj.greet.bind(obj); boundGreet(); // "Hello, Alice"箭头函数没有自己的this,它会捕获所在上下文的this值:
const obj = { name: "Bob", greet: function() { setTimeout(() => { console.log(`Hello, ${this.name}`); }, 100); } }; obj.greet(); // "Hello, Bob"3. 面向对象编程与原型链
3.1 构造函数与class语法
传统构造函数方式:
function Person(name, age) { this.name = name; this.age = age; } Person.prototype.greet = function() { console.log(`Hi, I'm ${this.name}`); }; const alice = new Person("Alice", 25); alice.greet();ES6 class语法(语法糖,底层仍是原型继承):
class Person { constructor(name, age) { this.name = name; this.age = age; } greet() { console.log(`Hi, I'm ${this.name}`); } } const bob = new Person("Bob", 30); bob.greet();3.2 原型链机制
JavaScript使用原型链实现继承:
function Animal(name) { this.name = name; } Animal.prototype.eat = function() { console.log(`${this.name} is eating.`); }; function Dog(name, breed) { Animal.call(this, name); this.breed = breed; } Dog.prototype = Object.create(Animal.prototype); Dog.prototype.constructor = Dog; Dog.prototype.bark = function() { console.log("Woof!"); }; const myDog = new Dog("Rex", "Labrador"); myDog.eat(); // "Rex is eating." myDog.bark(); // "Woof!"ES6继承语法更简洁:
class Animal { constructor(name) { this.name = name; } eat() { console.log(`${this.name} is eating.`); } } class Dog extends Animal { constructor(name, breed) { super(name); this.breed = breed; } bark() { console.log("Woof!"); } } const myDog = new Dog("Rex", "Labrador"); myDog.eat(); myDog.bark();3.3 现代对象操作技巧
对象解构:
const person = { name: "Alice", age: 25, job: "Developer" }; const { name, age } = person; console.log(name, age); // "Alice" 25展开运算符:
const obj1 = { a: 1, b: 2 }; const obj2 = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }可选链操作符(?.):
const user = { profile: { name: "Alice" } }; console.log(user?.profile?.name); // "Alice" console.log(user?.address?.street); // undefined (不会报错)4. 异步编程与现代JavaScript特性
4.1 从回调到Promise再到async/await
回调地狱示例:
function getUser(id, callback) { setTimeout(() => { callback({ id, name: `User${id}` }); }, 100); } getUser(1, (user) => { getUser(2, (user2) => { getUser(3, (user3) => { console.log([user, user2, user3]); }); }); });Promise解决方案:
function getUser(id) { return new Promise((resolve) => { setTimeout(() => { resolve({ id, name: `User${id}` }); }, 100); }); } getUser(1) .then(user => getUser(2)) .then(user2 => getUser(3)) .then(user3 => { console.log([user, user2, user3]); });async/await终极方案:
async function fetchUsers() { const user1 = await getUser(1); const user2 = await getUser(2); const user3 = await getUser(3); console.log([user1, user2, user3]); } fetchUsers();4.2 常用数组操作方法
map/filter/reduce三剑客:
const numbers = [1, 2, 3, 4, 5]; // map: 转换数组 const doubled = numbers.map(n => n * 2); // filter: 过滤数组 const evens = numbers.filter(n => n % 2 === 0); // reduce: 累积计算 const sum = numbers.reduce((acc, n) => acc + n, 0); console.log({ doubled, evens, sum });现代数组方法:
const users = [ { id: 1, name: "Alice", active: true }, { id: 2, name: "Bob", active: false }, { id: 3, name: "Charlie", active: true } ]; // find: 查找第一个符合条件的元素 const activeUser = users.find(user => user.active); // some: 是否有符合条件的元素 const hasInactive = users.some(user => !user.active); // every: 是否所有元素都符合条件 const allActive = users.every(user => user.active); console.log({ activeUser, hasInactive, allActive });4.3 ES6+重要特性
模板字符串:
const name = "Alice"; const age = 25; console.log(`My name is ${name} and I'm ${age} years old.`);默认参数:
function greet(name = "Guest") { console.log(`Hello, ${name}!`); } greet(); // "Hello, Guest!"剩余参数与展开运算符:
function sum(...numbers) { return numbers.reduce((acc, n) => acc + n, 0); } console.log(sum(1, 2, 3)); // 6 const arr1 = [1, 2, 3]; const arr2 = [4, 5, 6]; const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]5. 错误处理与调试技巧
5.1 try-catch与错误类型
基本错误处理:
try { // 可能出错的代码 const data = JSON.parse('invalid json'); } catch (error) { console.error('解析出错:', error.message); } finally { console.log('无论成功失败都会执行'); }自定义错误:
class ValidationError extends Error { constructor(message) { super(message); this.name = "ValidationError"; } } function validateInput(input) { if (!input) { throw new ValidationError("输入不能为空"); } } try { validateInput(""); } catch (error) { if (error instanceof ValidationError) { console.error("验证错误:", error.message); } else { console.error("未知错误:", error); } }5.2 调试技巧与性能优化
console的进阶用法:
console.time("arrayTest"); const arr = Array(1000000).fill().map((_, i) => i); console.timeEnd("arrayTest"); // 输出执行时间 console.table([ { name: "Alice", age: 25 }, { name: "Bob", age: 30 } ]); // 条件输出 console.assert(1 === 2, "1不等于2"); // 只有条件为false时输出性能优化建议:
- 避免在循环中创建函数
- 使用文档片段批量DOM操作
- 使用事件委托减少事件监听器
- 合理使用Web Worker处理耗时任务
内存泄漏常见原因:
- 意外的全局变量
- 未清除的定时器
- DOM引用未释放
- 闭包滥用
6. 模块化与现代开发工具
6.1 ES Modules基础
导出模块:
// math.js export function add(a, b) { return a + b; } export const PI = 3.14159;导入模块:
// app.js import { add, PI } from './math.js'; console.log(add(2, 3)); // 5 console.log(PI); // 3.14159默认导出:
// logger.js export default function(message) { console.log(`[LOG]: ${message}`); } // app.js import log from './logger.js'; log("Hello"); // "[LOG]: Hello"6.2 常用开发工具配置
VS Code推荐插件:
- ESLint - JavaScript代码检查
- Prettier - 代码格式化
- JavaScript (ES6) code snippets - 代码片段
- Debugger for Chrome - 调试
- Jest - 测试支持
package.json常见脚本:
{ "scripts": { "start": "node src/index.js", "dev": "nodemon src/index.js", "test": "jest", "lint": "eslint .", "build": "webpack --mode production" } }Babel配置示例(.babelrc):
{ "presets": [ ["@babel/preset-env", { "targets": { "browsers": ["last 2 versions", "not dead"] } }] ], "plugins": ["@babel/plugin-transform-runtime"] }7. 实战案例与常见问题解决
7.1 表单验证实用案例
class FormValidator { constructor(formId) { this.form = document.getElementById(formId); this.errors = {}; this.form.addEventListener('submit', (e) => { e.preventDefault(); if (this.validate()) { this.form.submit(); } }); } validate() { this.errors = {}; const inputs = this.form.querySelectorAll('[data-validate]'); inputs.forEach(input => { const rules = input.dataset.validate.split('|'); rules.forEach(rule => { const [ruleName, param] = rule.split(':'); if (ruleName === 'required' && !input.value.trim()) { this.addError(input, '此字段为必填项'); } if (ruleName === 'min' && input.value.length < parseInt(param)) { this.addError(input, `至少需要${param}个字符`); } if (ruleName === 'email' && !/^\S+@\S+\.\S+$/.test(input.value)) { this.addError(input, '请输入有效的邮箱地址'); } }); }); return Object.keys(this.errors).length === 0; } addError(input, message) { if (!this.errors[input.name]) { this.errors[input.name] = []; } this.errors[input.name].push(message); // 显示错误提示 const errorElement = document.createElement('div'); errorElement.className = 'error-message'; errorElement.textContent = message; input.parentNode.appendChild(errorElement); } } // 使用示例 new FormValidator('myForm');7.2 常见错误与解决方案
Cannot read property 'xxx' of undefined/null原因:尝试访问未定义或null值的属性 解决方案:使用可选链操作符或条件判断
// 不好的写法 const street = user.address.street; // 好的写法 const street = user?.address?.street; // 或 const street = user && user.address && user.address.street;Unexpected token '<'原因:通常是因为请求返回了HTML而不是预期的JSON 解决方案:检查API端点是否正确,确保返回的是JSON
Maximum call stack size exceeded原因:无限递归调用 解决方案:检查递归函数的终止条件
Cross-Origin Request Blocked原因:跨域请求被阻止 解决方案:配置CORS或使用代理
TypeError: xxx is not a function原因:尝试调用非函数类型的值 解决方案:检查变量是否确实是一个函数
8. 性能优化与安全实践
8.1 前端性能优化技巧
减少重绘和回流
- 使用transform和opacity实现动画
- 批量DOM操作
- 使用文档片段(document.createDocumentFragment())
代码分割与懒加载
// 动态导入 const module = await import('./module.js'); // React中的懒加载 const LazyComponent = React.lazy(() => import('./LazyComponent'));防抖与节流
// 防抖:最后一次操作后等待一段时间执行 function debounce(fn, delay) { let timer; return function() { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, arguments), delay); }; } // 节流:固定时间间隔执行一次 function throttle(fn, interval) { let lastTime = 0; return function() { const now = Date.now(); if (now - lastTime >= interval) { fn.apply(this, arguments); lastTime = now; } }; }
8.2 JavaScript安全最佳实践
避免XSS攻击
- 总是对用户输入进行转义
- 使用textContent而不是innerHTML
- 设置Content Security Policy (CSP)
防止CSRF攻击
- 使用CSRF令牌
- 设置SameSite cookie属性
安全存储敏感数据
- 不要在前端存储密码等敏感信息
- 使用HttpOnly和Secure标记的cookie
输入验证
function sanitizeInput(input) { return input.replace(/</g, "<").replace(/>/g, ">"); }使用安全的API
- 避免使用eval()
- 使用JSON.parse()而不是eval()解析JSON
- 使用模板字符串而不是字符串拼接构建HTML
9. 测试与调试进阶
9.1 单元测试基础
使用Jest进行测试:
// math.js export function add(a, b) { return a + b; } // math.test.js import { add } from './math'; test('adds 1 + 2 to equal 3', () => { expect(add(1, 2)).toBe(3); }); describe('add function', () => { it('should add two numbers correctly', () => { expect(add(2, 3)).toBe(5); expect(add(-1, 1)).toBe(0); expect(add(0, 0)).toBe(0); }); });9.2 调试技巧进阶
Chrome开发者工具技巧:
- 条件断点:右键点击行号,选择"Add conditional breakpoint"
- 日志点:在不修改代码的情况下添加console.log
- 黑盒脚本:忽略第三方库的调试
- 性能分析:使用Performance面板记录和分析运行时性能
Node.js调试:
node --inspect-brk app.js然后在Chrome中访问chrome://inspect进行调试
9.3 错误监控与日志
Sentry集成示例:
import * as Sentry from '@sentry/browser'; Sentry.init({ dsn: 'YOUR_DSN_HERE', release: 'my-project@1.0.0', environment: 'production' }); try { riskyOperation(); } catch (error) { Sentry.captureException(error); }自定义错误日志:
function logError(error, context = {}) { const errorData = { timestamp: new Date().toISOString(), message: error.message, stack: error.stack, ...context }; // 发送到服务器或保存到IndexedDB sendToServer('/log-error', errorData); }10. 现代JavaScript生态系统
10.1 流行框架概览
React
import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}> Increment </button> </div> ); }Vue
import { createApp, ref } from 'vue'; const app = createApp({ setup() { const count = ref(0); return { count, increment: () => count.value++ }; }, template: ` <div> <p>Count: {{ count }}</p> <button @click="increment">Increment</button> </div> ` }); app.mount('#app');Angular
import { Component } from '@angular/core'; @Component({ selector: 'app-counter', template: ` <div> <p>Count: {{ count }}</p> <button (click)="increment()">Increment</button> </div> ` }) export class CounterComponent { count = 0; increment() { this.count++; } }
10.2 构建工具比较
Webpack
- 高度可配置
- 强大的代码分割能力
- 丰富的插件生态系统
Vite
- 极快的启动速度
- 原生ES模块支持
- 开箱即用的配置
Rollup
- 适合库开发
- 生成更小的包
- 简单的配置
10.3 TypeScript基础
类型注解:
function greet(name: string): string { return `Hello, ${name}!`; } interface User { id: number; name: string; age?: number; // 可选属性 } const user: User = { id: 1, name: "Alice" };泛型:
function identity<T>(arg: T): T { return arg; } const output = identity<string>("hello");类与继承:
class Animal { constructor(public name: string) {} move(distance: number = 0) { console.log(`${this.name} moved ${distance}m.`); } } class Dog extends Animal { constructor(name: string, public breed: string) { super(name); } bark() { console.log("Woof!"); } } const myDog = new Dog("Rex", "Labrador"); myDog.bark(); myDog.move(10);11. 浏览器API与Web标准
11.1 DOM操作最佳实践
高效DOM操作:
// 不好的做法:多次重排 for (let i = 0; i < 100; i++) { document.body.appendChild(document.createElement('div')); } // 好的做法:使用文档片段 const fragment = document.createDocumentFragment(); for (let i = 0; i < 100; i++) { fragment.appendChild(document.createElement('div')); } document.body.appendChild(fragment);事件委托:
// 不好的做法:为每个元素添加监听器 document.querySelectorAll('.item').forEach(item => { item.addEventListener('click', handleClick); }); // 好的做法:事件委托 document.querySelector('.container').addEventListener('click', (e) => { if (e.target.matches('.item')) { handleClick(e); } });11.2 现代浏览器API
Web Storage:
// localStorage localStorage.setItem('theme', 'dark'); const theme = localStorage.getItem('theme'); // sessionStorage sessionStorage.setItem('token', 'abc123');Geolocation API:
navigator.geolocation.getCurrentPosition( (position) => { console.log(position.coords.latitude, position.coords.longitude); }, (error) => { console.error(error.message); } );Web Workers:
// main.js const worker = new Worker('worker.js'); worker.postMessage({ data: 'Hello' }); worker.onmessage = (e) => { console.log('From worker:', e.data); }; // worker.js self.onmessage = (e) => { const result = e.data.data.toUpperCase(); self.postMessage(result); };11.3 图形与动画API
Canvas基础:
const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); ctx.fillStyle = 'red'; ctx.fillRect(10, 10, 100, 100); ctx.beginPath(); ctx.arc(200, 75, 50, 0, Math.PI * 2); ctx.stroke();WebGL入门:
const canvas = document.getElementById('glCanvas'); const gl = canvas.getContext('webgl'); if (!gl) { alert('WebGL not supported'); } gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT);12. Node.js基础与全栈开发
12.1 Node.js核心模块
HTTP服务器:
const http = require('http'); const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Hello World\n'); }); server.listen(3000, () => { console.log('Server running at http://localhost:3000/'); });文件系统操作:
const fs = require('fs').promises; async function readFiles() { try { const data = await fs.readFile('file.txt', 'utf8'); console.log(data); await fs.writeFile('copy.txt', data); } catch (err) { console.error(err); } } readFiles();12.2 Express框架基础
基本应用:
const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('Hello World!'); }); app.post('/api/users', (req, res) => { // 处理POST请求 res.json({ success: true }); }); app.listen(3000, () => { console.log('Server is running on port 3000'); });中间件:
// 日志中间件 app.use((req, res, next) => { console.log(`${req.method} ${req.url}`); next(); }); // 静态文件服务 app.use(express.static('public')); // 解析JSON请求体 app.use(express.json());12.3 数据库连接
MongoDB (Mongoose):
const mongoose = require('mongoose'); mongoose.connect('mongodb://localhost:27017/mydb', { useNewUrlParser: true, useUnifiedTopology: true }); const userSchema = new mongoose.Schema({ name: String, email: { type: String, required: true } }); const User = mongoose.model('User', userSchema); async function createUser() { const user = new User({ name: 'Alice', email: 'alice@example.com' }); await user.save(); console.log('User created:', user); } createUser();SQL (Sequelize):
const { Sequelize, DataTypes } = require('sequelize'); const sequelize = new Sequelize('sqlite::memory:'); const User = sequelize.define('User', { name: DataTypes.STRING, email: { type: DataTypes.STRING, allowNull: false } }); async function test() { await sequelize.sync(); const user = await User.create({ name: 'Bob', email: 'bob@example.com' }); console.log(user.toJSON()); } test();13. 设计模式与架构原则
13.1 常见JavaScript设计模式
单例模式:
class Logger { constructor() { if (Logger.instance) { return Logger.instance; } this.logs = []; Logger.instance = this; } log(message) { this.logs.push(message); console.log(message); } } const logger1 = new Logger(); const logger2 = new Logger(); console.log(logger1 === logger2); // true观察者模式:
class EventEmitter { constructor() { this.events = {}; } on(event, listener) { if (!this.events[event]) { this.events[event] = []; } this.events[event].push(listener); } emit(event, ...args) { if (this.events[event]) { this.events[event].forEach(listener => listener(...args)); } } } const emitter = new EventEmitter(); emitter.on('data', (data) => { console.log('Received data:', data); }); emitter.emit('data', { id: 1 }); // "Received data: { id: 1 }"工厂模式:
class Car { constructor(options) { this.model = options.model || 'Unknown'; this.year = options.year || new Date().getFullYear(); } } class Truck { constructor(options) { this.capacity = options.capacity || 1; this.model = options.model || 'Unknown'; } } class VehicleFactory { createVehicle(type, options) { switch (type) { case 'car': return new Car(options); case 'truck': return new Truck(options); default: throw new Error('Unknown vehicle type'); } } } const factory = new VehicleFactory(); const myCar = factory.createVehicle('car', { model: 'Sedan' }); const myTruck = factory.createVehicle('truck', { capacity: 5 });13.2 SOLID原则应用
单一职责原则(SRP)
// 不好的做法 class User { constructor(name, email) { this.name = name; this.email = email; } saveToDatabase() { // 保存到数据库 } sendEmail() { // 发送邮件 } } // 好的做法 class User { constructor(name, email) { this.name = name; this.email = email; } } class UserRepository { save(user) { // 保存到数据库 } } class EmailService { send(user, message) { // 发送邮件 } }开闭原则(OCP)
// 不好的做法 class Logger { log(message, type) { if (type === 'console') { console.log(message); } else if (type === 'file') { // 写入文件 } } } // 好的做法 class Logger { log(message) { throw new Error('Method not implemented'); } } class ConsoleLogger extends Logger { log(message) { console.log(message); } } class FileLogger extends Logger { log(message) { // 写入文件 } }里氏替换原则(LSP)
class Bird { fly() { console.log('Flying'); } } class Duck extends Bird { quack() { console.log('Quack'); } } class Penguin extends Bird { fly() { throw new Error('Penguins cannot fly'); } } // 违反LSP原则,因为Penguin不能替换Bird接口隔离原则(ISP)
// 不好的做法 class Worker { work() {} eat() {} } // 好的做法 class Workable { work() {} } class Eatable { eat() {} } class Worker implements Workable, Eatable { work() {} eat() {} } class Robot implements Workable { work() {} }依赖倒置原则(DIP)
// 不好的做法 class LightBulb { turnOn() {} turnOff() {} } class Switch { constructor(bulb) { this.bulb = bulb; } operate() { // 操作灯泡 } } // 好的做法 class Switchable { turnOn() {} turnOff() {} } class LightBulb implements Switchable { turnOn() {} turnOff() {} } class Switch { constructor(device) { this.device = device; } operate() { // 操作任何Switchable设备 } }
14. 算法与数据结构基础
14.1 常见算法实现
快速排序:
function quickSort(arr) { if (arr.length <= 1) return arr; const pivot = arr[0]; const left = []; const right = []; for (let i = 1; i < arr.length; i++) { if (arr[i] < pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } return [...quickSort(left), pivot, ...quickSort(right)]; } console.log(quickSort([3, 6, 8, 10, 1, 2, 1])); // [1, 1, 2, 3, 6, 8, 10]二分查找:
function binarySearch(arr, target) { let left = 0; let right = arr.length - 1; while (left <= right) { const mid = Math.floor((left + right) / 2); if (arr[mid] === target) { return mid; } else if (arr[mid] < target) { left = mid + 1; } else { right = mid - 1; } } return -1; } const sortedArr = [1, 3, 5, 7, 9]; console.log(binarySearch(sortedArr, 5)); // 2 console.log(binarySearch(sortedArr, 2)); // -114.2 数据结构实现
链表:
class ListNode { constructor(value) { this.value = value; this.next = null; } } class LinkedList { constructor() { this.head = null; this.tail = null; this.length = 0; } append(value) { const newNode = new ListNode(value); if (!this.head) { this.head = newNode; this.tail = newNode; } else { this.tail.next = newNode; this.tail = newNode; } this.length++; } print() { let current = this.head; while (current) { console.log(current.value); current = current.next; } } } const list = new LinkedList(); list.append(1); list.append(2); list.append(3); list.print(); // 1, 2, 3哈希表:
class HashTable { constructor(size = 53) { this.keyMap = new Array(size); } _hash(key) { let total = 0; const WEIRD_PRIME