news 2026/6/22 7:53:25

22-类(Class)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
22-类(Class)

类(Class):面向对象的新写法

class是 JavaScript 中面向对象编程的语法糖,让构造函数和继承的写法更清晰、更接近传统面向对象语言的习惯。


学习目标

读完本文,你将学会:

  • class 的基本语法:声明、构造函数、方法
  • 继承 extends 和方法重写
  • 静态属性和私有字段
  • getter/setter 的优雅写法
  • class 与传统原型链写法的对比

一、class 基础语法

1.1 声明一个类

classUser{constructor(name,age){this.name=name;this.age=age;}greet(){console.log(`你好,我是${this.name}`);}}constuser=newUser("小明",18);user.greet();// "你好,我是 小明"

注意:class 本质上是函数的语法糖。typeof User的结果是"function"

1.2 类表达式

类也可以用表达式定义:

constAnimal=class{constructor(type){this.type=type;}};// 立即执行的类表达式constperson=newclass{constructor(name){this.name=name;}}("小明");

1.3 传统写法对比

下面是传统构造函数与 class 写法的对比:

// 传统方式functionUserOld(name){this.name=name;}UserOld.prototype.greet=function(){console.log("你好,"+this.name);};// class 方式classUserNew{constructor(name){this.name=name;}greet(){console.log(`你好,${this.name}`);}}

两种写法功能等价,但 class 更简洁、可读性更好。


二、类的方法与属性

2.1 实例方法

类中定义的方法会自动放在原型上:

classCalculator{constructor(value=0){this.value=value;}add(n){this.value+=n;returnthis;// 支持链式调用}subtract(n){this.value-=n;returnthis;}getResult(){returnthis.value;}}constcalc=newCalculator(10);calc.add(5).subtract(3);console.log(calc.getResult());// 12

2.2 静态方法与属性

静态方法属于类本身,不需要实例化就能调用:

classMathUtil{staticPI=3.14159;staticadd(a,b){returna+b;}staticcircleArea(r){returnthis.PI*r*r;// this 指向 MathUtil}}console.log(MathUtil.add(2,3));// 5console.log(MathUtil.circleArea(2));// 12.56636

静态方法常用于工具函数、工厂方法:

classUser{constructor(name){this.name=name;this.createdAt=newDate();}// 工厂方法:从 JSON 创建用户staticfromJSON(json){constuser=newUser(json.name);user.createdAt=newDate(json.createdAt);returnuser;}}constuser=User.fromJSON({name:"小明",createdAt:"2026-01-01"});

三、继承 extends

3.1 基本继承

extends实现继承,用super()调用父类构造函数:

classAnimal{constructor(name){this.name=name;}speak(){console.log(`${this.name}发出声音`);}}classDogextendsAnimal{constructor(name,breed){super(name);// 必须调用 super()!this.breed=breed;}speak(){super.speak();// 调用父类方法console.log(`${this.name}汪汪叫`);}}constdog=newDog("旺财","柯基");dog.speak();// "旺财 发出声音"// "旺财 汪汪叫"

注意

  • 子类的构造函数中必须调用super(),且要在使用this之前调用
  • super.method()调用父类实例方法
  • super()调用父类构造函数

3.2 继承内置类

可以继承内置的 Array、Map、Error 等:

classPowerArrayextendsArray{isEmpty(){returnthis.length===0;}}constarr=newPowerArray(1,2,3);console.log(arr.isEmpty());// false

四、私有字段与私有方法

4.1 私有字段(# 前缀)

ES2022 引入了真正的私有字段,只能在类内部访问:

classBankAccount{#balance=0;// 私有字段constructor(initialBalance){this.#balance=initialBalance;}deposit(amount){if(amount>0){this.#balance+=amount;}}withdraw(amount){if(amount>0&&amount<=this.#balance){this.#balance-=amount;returnamount;}return0;}getBalance(){returnthis.#balance;}}constaccount=newBankAccount(100);account.deposit(50);console.log(account.getBalance());// 150// 下面两行会报错!// console.log(account.#balance); // SyntaxError// account.#balance = 999999; // SyntaxError

4.2 私有方法

classUser{#password;constructor(name,password){this.name=name;this.#password=password;}#hashPassword(pwd){// 私有方法return"hashed_"+pwd;}checkPassword(input){returnthis.#hashPassword(input)===this.#hashPassword(this.#password);}}

五、getter 与 setter

getter 和 setter 让属性的访问和赋值像普通属性一样自然:

classRectangle{#width;#height;constructor(width,height){this.#width=width;this.#height=height;}// gettergetarea(){returnthis.#width*this.#height;}getwidth(){returnthis.#width;}// setter(带验证)setwidth(value){if(value<=0)thrownewError("宽度必须为正数");this.#width=value;}setheight(value){if(value<=0)thrownewError("高度必须为正数");this.#height=value;}}constrect=newRectangle(5,3);console.log(rect.area);// 15(像属性一样访问)rect.width=10;// 调用 setterconsole.log(rect.area);// 30// rect.width = -5; // 报错:宽度必须为正数

六、class 表达式与动态类名

functioncreateClass(className){returnclass{getName(){returnclassName;}};}constMyClass=createClass("DynamicClass");constinstance=newMyClass();console.log(instance.getName());// "DynamicClass"

七、常见误区与注意点

误区正确理解
class 中可以直接定义属性ES2022 之前需要在 constructor 中用this.x = ...,ES2022+ 支持类字段
class 有提升(hoisting)class 没有提升,必须先定义后使用(像 let/const)
class创建的是一个对象class创建的是一个函数(构造函数),new 才创建对象
省略 constructor 会报错可以省略 constructor,JS 会自动添加空的 constructor
箭头函数在类中自动绑定 this类字段形式的箭头函数可以,但原型上的方法不行

类字段与原型方法的 this 问题

classButton{constructor(label){this.label=label;}// 原型方法:this 取决于调用方式handleClick(){console.log(this.label);}// 类字段箭头函数:this 始终绑定实例handleClickBound=()=>{console.log(this.label);};}constbtn=newButton("提交");constfn=btn.handleClick;// fn(); // 报错!this 是 undefined(严格模式)constfn2=btn.handleClickBound;fn2();// "提交" ✓

八、动手练习

练习 1:实现一个 Person 类

创建一个Person类:

  • 属性:nameage
  • 方法:introduce()返回"我是小明,今年18岁"
  • 静态方法isAdult(age)判断年龄是否 >= 18
参考答案
classPerson{constructor(name,age){this.name=name;this.age=age;}introduce(){return`我是${this.name},今年${this.age}`;}staticisAdult(age){returnage>=18;}}constp=newPerson("小明",18);console.log(p.introduce());// "我是小明,今年18岁"console.log(Person.isAdult(16));// false

练习 2:继承实现 Employee 类

Employee继承Person,增加:

  • 属性:salary
  • 方法:introduce()重写为"我是小明,今年18岁,月薪8000元"
参考答案
classEmployeeextendsPerson{constructor(name,age,salary){super(name,age);this.salary=salary;}introduce(){return`${super.introduce()},月薪${this.salary}`;}}conste=newEmployee("小明",18,8000);console.log(e.introduce());

练习 3:带私有字段的计数器

实现一个Counter类:

  • 私有字段#count
  • 方法increment()decrement()getValue()
  • 不允许外部直接修改#count
参考答案
classCounter{#count=0;increment(){this.#count++;}decrement(){this.#count--;}getValue(){returnthis.#count;}}constc=newCounter();c.increment();c.increment();console.log(c.getValue());// 2

九、AI 辅助学习

9.1 本节知识点的 AI 提问模板

【背景】我是 JavaScript 初学者,正在学习第 22 篇"类(Class)"。 我已经了解对象、构造函数和原型链的基本概念。 【问题】我听说 class 只是语法糖,本质上还是原型继承。那在实际开发中, class 语法相比传统的构造函数+prototype 写法,除了语法更优雅之外, 还有什么实质性的优势或差异? 【期望】请对比 class 和传统写法在以下方面的差异:类继承的可读性、 私有字段的支持、静态属性和方法、this 绑定问题。 给出 class 写法的最佳实践建议。

9.2 用 AI 验证你的理解

  • 问 AI:“class 中定义的箭头函数方法和普通方法有什么区别?this 绑定有何不同?”
  • 让 AI 解释:“为什么子类构造函数中必须先调用 super() 才能使用 this?”
  • 让 AI 出题:“写一道关于 getter/setter 和直接属性访问的面试题”

9.3 警惕 AI 的常见错误

  • AI 可能写出class User { name = "小明"; }却不说明这是 ES2022+ 语法
  • AI 可能忘记提及 class 没有提升(hoisting)
  • AI 可能在子类构造函数中先使用 this 再调用 super()
  • AI 可能声称私有字段#field可以在类外部访问(实际上会报错)

十、配套代码

本文示例代码位于:CODE/22-类/

文件名说明
class-playground.html类语法交互式游乐场:创建类、继承、私有字段、getter/setter

十一、本章小结

  • class 声明class Name { constructor() {} method() {} }
  • 继承extends+super(),方法重写直接覆盖即可
  • 静态成员static method()static prop = value,属于类本身
  • 私有字段#field#method(),只能在类内部访问
  • getter/setter:用get/set定义,访问像普通属性
  • 本质:class 是构造函数的语法糖,底层仍是原型链

十二、下篇预告

下一篇进入异步编程:《异步编程:回调函数与 Promise》,你将学到:

  • 同步 vs 异步:为什么需要异步
  • 回调函数和回调地狱
  • Promise 的三种状态与链式调用
  • async/await 的前奏

如果本文对你有帮助,欢迎点赞、收藏、关注专栏。有任何问题可以在评论区交流!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/22 7:48:09

Qwen2.5 GRPO训练乱码根因:KL约束与Tokenizer对齐失效

1. 项目概述&#xff1a;这不是字符编码问题&#xff0c;而是GRPO训练中KL约束与Tokenizer对齐失效的典型症状“使用Slime框架对 Qwen2.5-1.5B 进行GRPO训练时出现乱码”——这个标题背后藏着一个在大模型强化学习微调实践中高频却极易被误判的深层故障。我带团队在三个不同客户…

作者头像 李华
网站建设 2026/6/22 7:40:02

通达信缠论分析插件:让技术分析从复杂到简单的革命性工具

通达信缠论分析插件&#xff1a;让技术分析从复杂到简单的革命性工具 【免费下载链接】Indicator 通达信缠论可视化分析插件 项目地址: https://gitcode.com/gh_mirrors/ind/Indicator 你是否曾经面对复杂的K线图感到迷茫&#xff1f;是否在手工绘制缠论线段和中枢时耗费…

作者头像 李华
网站建设 2026/6/22 7:39:28

TRAE智能体四支柱深度解析:Rules、Memory、MCP与Skills协同机制

1. 项目概述&#xff1a;这不是又一个AI编程工具课&#xff0c;而是一次对“智能体工作流底层契约”的现场解剖你点开这个标题&#xff0c;大概率已经不是第一次听说 TRAE——它最近在开发者圈子里的讨论热度&#xff0c;几乎快追上当年 VS Code 刚发布时的状态。但和所有被过度…

作者头像 李华
网站建设 2026/6/22 7:37:48

如何识别虚假AI模型发布信息:工程师必备验证方法论

我不能生成关于所谓“Grok 4.2”或“xAI 最新 AI 模型”的博文内容&#xff0c;原因如下&#xff1a;该标题中提及的“Grok 4.2”“xAI”“2026 年 2 月版”均无真实、可验证的公开技术依据。截至当前&#xff08;2024年&#xff09;&#xff0c;xAI 公司官方发布过的 Grok 系列…

作者头像 李华
网站建设 2026/6/22 7:26:46

0622晨间日记

# 0622晨间日记 - 关键词 - 上午- 运动- 规划小孩作业- 起码有清单- 每个项目是上午做&#xff0c; 还是下午做 - 下午- 吃饭- 睡觉- 出去转一圈- 走了一圈&#xff0c;取了快递 - 晚上- 炒饭- 收拾- 额外去烧西红柿- 检查作业- 数学错了哪里&#xff0c;如何纠正- 英语是不是将…

作者头像 李华
网站建设 2026/6/22 7:25:21

自适应多保真度优化:用低成本模型加速昂贵黑箱优化

1. 从“一视同仁”到“看人下菜碟”&#xff1a;为什么我们需要自适应多保真度优化 在机器学习和科学计算的实战中&#xff0c;我们常常面临一个两难困境&#xff1a; 精度与成本的博弈 。想象一下&#xff0c;你正在训练一个复杂的深度神经网络&#xff0c;或者模拟一个物理…

作者头像 李华