2026/5/17 18:58:02
网站建设
项目流程
50m专线做视频网站,邢台做网站建设优化制作公司,做门户网站找哪家公司,做网站赚外快搞懂 ES6 的class和继承#xff1a;从写代码的“土办法”到优雅编程你有没有过这样的经历#xff1f;在早期写 JavaScript 时#xff0c;想做个“人”这个对象#xff0c;结果只能靠函数模拟#xff1a;function Person(name, age) {this.name name;this.age age;
}
Per…搞懂 ES6 的class和继承从写代码的“土办法”到优雅编程你有没有过这样的经历在早期写 JavaScript 时想做个“人”这个对象结果只能靠函数模拟function Person(name, age) { this.name name; this.age age; } Person.prototype.sayHello function() { console.log(Hello, Im ${this.name}); };看着像那么回事但总觉得别扭——明明是面向对象的思想语法却像是拼凑出来的。更头疼的是一旦要搞个学生、老师这些子类就得手动操作原型链一不小心就出错。直到 ES6 出现了class关键字一切都变了。为什么我们需要class随着前端项目越来越复杂单靠对象字面量和函数已经撑不住了。React、Vue 这些框架开始流行组件化开发我们迫切需要一种更清晰、更有组织性的方式来管理代码逻辑。ES6 的class就是在这种背景下诞生的。它不是新发明了一套继承机制而是给老的原型继承穿上了一件漂亮的新外衣——也就是常说的“语法糖”。但它这件衣服穿得太好看了以至于很多人以为 JavaScript 突然变成了 Java 那样的语言。其实不然。class只是让原本晦涩难懂的原型操作变得直观易读了。class到底怎么用一个例子讲明白来看一个最简单的例子class Person { constructor(name, age) { this.name name; this.age age; } sayHello() { console.log(Hello, Im ${this.name}); } static info() { console.log(This is a Person class); } }这段代码做了三件事-构造函数constructor创建实例时自动执行用来初始化属性-实例方法sayHello()每个由new Person()创建的对象都能调用-静态方法info()属于类本身不归实例所有直接通过Person.info()调用。使用起来也很简单const p new Person(Alice, 30); p.sayHello(); // 输出: Hello, Im Alice Person.info(); // 输出: This is a Person class注意你不能直接调用Person()必须用new否则会报错。这是强制规范防止误用。class背后还是原型链只是你看不见虽然写法看起来像 Java 或 C但底层依然是 JavaScript 原有的那一套——基于原型prototype-based的对象系统。当你写下class PersonJavaScript 实际上做了这些事把Person当作一个函数构造器把所有实例方法如sayHello挂到Person.prototype上静态方法则直接挂在Person函数上用new实例化时执行constructor并把this绑定到新对象。所以下面这行代码依然成立p.__proto__ Person.prototype; // true也就是说方法查找还是走原型链的老路子。class只是帮你省去了手动写Person.prototype.sayHello ...的麻烦。让数据更安全getter 和 setter有时候你不希望别人随意修改某些属性比如银行账户余额。这时候可以用get和set来控制访问。class BankAccount { constructor(initialBalance 0) { this._balance initialBalance; // _ 表示“私有”约定 } get balance() { return this._balance; } set balance(amount) { if (amount 0) throw new Error(Balance cannot be negative); this._balance amount; } deposit(money) { this.balance money; } withdraw(money) { if (money this.balance) throw new Error(Insufficient funds); this._balance - money; } }现在你可以像读普通属性一样获取余额const account new BankAccount(100); console.log(account.balance); // 100 account.deposit(50); console.log(account.balance); // 150 account.balance -10; // 抛错这里的_balance并非真正的私有字段ES2022 之前没有只是一个命名约定提醒开发者“别在外面直接改我”。子类怎么来用extends实现继承假设我们要做一个学生类他也有人的基本信息但多了个年级属性还能学习。以前你可能得复制一遍Person的代码再加点东西但现在只需要一句话class Student extends Person { constructor(name, age, grade) { super(name, age); // 必须先调用父类构造函数 this.grade grade; } study() { console.log(${this.name} is studying...); } // 重写父类方法 sayHello() { console.log(Hi, Im ${this.name}, a student in grade ${this.grade}); } }关键点来了-extends表示继承自Person-super(name, age)是调用父类的constructor必须在使用this之前调用-sayHello方法被重写了子类优先- 新增了study方法扩展功能。试试看效果const s new Student(Tom, 20, Junior); s.sayHello(); // Hi, Im Tom, a student in grade Junior s.study(); // Tom is studying...多态也生效了function greetEveryone(people) { people.forEach(person person.sayHello()); } greetEveryone([ new Person(Mr. Lee, 45), new Student(Lucy, 19, Freshman) ]); // 各自用自己的方式打招呼继承背后的原理原型链是如何延伸的你以为extends是魔法其实它也只是帮你连好了原型链。当你说class Student extends PersonJavaScript 在背后悄悄做了几件事Student.prototype.__proto__ Person.prototype→ 所以实例方法可以向上查找Student.__proto__ Person→ 所以静态方法也能继承super()实际就是Parent.call(this, ...args)的语法糖方法调用遵循“就近原则”找不到就往上找。这也解释了为什么s instanceof Student; // true s instanceof Person; // true因为instanceof查的就是原型链。再进一步多层继承与方法增强你可以继续派生更具体的类比如研究生class GraduateStudent extends Student { constructor(name, age, grade, researchTopic) { super(name, age, grade); this.researchTopic researchTopic; } sayHello() { super.sayHello(); // 先执行父类逻辑 console.log(Researching on: ${this.researchTopic}); } static createFromStudent(student, topic) { const { name, age, grade } student; return new GraduateStudent(name, age, grade, topic); } } const gs new GraduateStudent(Bob, 25, PhD, AI Ethics); gs.sayHello(); // 输出: // Hi, Im Bob, a student in grade PhD // Researching on: AI Ethics这里展示了两个高级技巧-调用super.sayHello()保留父类行为的同时增加新功能-静态工厂方法提供更灵活的对象创建方式封装细节。实际应用场景什么时候该用类别以为class只是用来炫技的。在真实项目中它有很多实用场景✅ UI 组件定义虽然 React 现在主推函数组件 Hooks但在 Vue 2 和一些老项目里类仍然是组织组件逻辑的重要方式。class UserCard extends Component { render() { return divHello ${this.props.name}/div; } }✅ 工具类封装比如封装一个 HTTP 请求客户端class HttpClient { constructor(baseURL) { this.baseURL baseURL; } async get(url) { return fetch(this.baseURL url).then(r r.json()); } static createJsonPlaceholder() { return new HttpClient(https://jsonplaceholder.typicode.com); } }✅ 游戏或管理系统中的实体建模在一个学生管理系统中常见的继承结构可能是Person ↓ Student ↓ GraduateStudent共用姓名、年龄等基础属性逐级扩展能力减少重复代码。使用类的最佳实践别踩这些坑class很强大但也容易滥用。记住这几个建议❌ 不要过度继承超过两到三层的继承链会让代码难以维护。优先考虑组合代替继承// 更好的方式通过对象组合功能 const CanStudy { study() { /*...*/ } }; Object.assign(Student.prototype, CanStudy);✅ 合理使用静态方法静态方法适合做工具函数不要在里面引用this或实例状态。✅ 保护内部状态尽管 ES2022 才正式支持私有字段#privateField但你可以用_前缀表示“请勿外部访问”this._password secret; // 约定俗成✅ 方法重写要小心确保重写后的行为符合预期尤其是被其他模块依赖的方法避免破坏 Liskov 替换原则。✅ 大项目推荐搭配 TypeScript给类加上类型注解能极大提升可读性和安全性class Person { constructor(public name: string, public age: number) {} }总结一下你真正需要掌握的是什么class是语法糖本质仍是原型继承extends和super让继承变得简洁清晰支持构造函数、实例方法、静态方法、getter/setter 完整特性多态和instanceof依然有效提高了代码复用性、可读性和团队协作效率。更重要的是学会用类去抽象现实世界中的事物关系而不是为了用而用。未来随着私有字段、装饰器等新特性的普及JavaScript 的类模型还会变得更强大。但无论怎么变理解其背后的原型机制才是你驾驭这门语言的根本。如果你正在写一个复杂的前端应用不妨试着把核心模型抽象成类。你会发现代码突然变得有条理了。如果你在实现过程中遇到了其他挑战欢迎在评论区分享讨论。