JavaScript 中的 Class 类

在这里插入图片描述

🔥 引言

在ECMAScript 2015(ES6)中,class 关键字被引入,为JavaScript带来了一种更接近传统面向对象语言的语法糖。类是创建对象的模板,它们封装了数据(属性)和行为(方法),是实现面向对象编程的基础单元。🎈


🎯 基础知识

在JavaScript这门灵活多变的语言中,Class是ES6引入的一个重要特性,它为面向对象编程提供了一种更简洁、更清晰的语法糖。通过Class,我们可以更容易地创建对象和管理继承关系。本文将从基础到进阶,带你深入探索Class的世界,让代码更加优雅且易于理解。👩‍🏫

基本声明

Class关键字用于定义一个类。类是一种蓝图,用于创建具有特定属性和方法的对象。

class Person {constructor(name, age) {this.name = name;this.age = age;}sayHello() {console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);}
}
  • constructor 是类的构造函数,用于初始化新创建的实例。
  • sayHello 是类的一个方法。

创建实例

创建类的实例就像调用构造函数一样简单:

const alice = new Person('Alice', 30);
alice.sayHello(); // 输出: Hello, my name is Alice and I am 30 years old.

🏗️ 构造函数 (Constructor)

构造函数是一个特殊的方法,用于初始化新创建的对象。每当你使用 new 关键字创建类的实例时,构造函数会被自动调用。

// 定义一个Person类,包含姓名(name)和年龄(age)属性
class Person {/*** 构造函数* @param {string} name - 人的名字* @param {number} age - 人的年龄*/constructor(name, age) {// 使用'this'关键字给实例绑定属性// 'this'在此处指的是新创建的Person实例this.name = name; // 绑定name属性this.age = age;   // 绑定age属性}
}// 使用'new'关键字创建Person类的实例
const alice = new Person('Alice', 30);// 访问alice实例的name属性,输出:Alice
console.log(alice.name); // 输出: Alice
  • 构造函数签名:构造函数的名称必须是constructor,且没有返回值类型声明。
  • 参数:构造函数可以接收任意数量的参数,这些参数用于初始化实例的属性。
  • this的使用:在构造函数内部,this是一个特殊的关键字,它指向新创建的实例对象。
  • 默认值与验证:虽然本例未展示,但在构造函数中可以加入逻辑来为参数设置默认值或进行有效性验证。
  • 自动调用:实例化时,构造函数自动执行,无需手动调用

🔐 私有字段 (Private Fields)

ES2022 引入了私有字段的概念,通过在字段名前加 # 符号来声明,确保了字段的私密性和安全性。

class User {// 声明一个私有字段 #password#password;/*** 构造函数,用于初始化User实例* @param {string} password - 用户的密码*/constructor(password) {// 使用私有字段 #password 存储密码this.#password = password;}/*** 公共方法,安全地获取密码(实际应用中应谨慎处理密码)* @returns {string} 返回存储的密码*/getPassword() {return this.#password;}
}// 创建User类的实例
const user = new User('mySecret');// 通过公共方法访问私有字段
console.log(user.getPassword()); // 输出: mySecret// 尝试直接访问私有字段会导致语法错误
// console.log(user.#password); // 这里会引发错误,因为#password是私有的
  • 封装性增强:私有字段有效限制了对类内部状态的直接访问,促进了良好的封装实践。
  • 安全性提升:防止外部代码无意或恶意修改类的内部数据,减少潜在的bug。
  • 设计原则:鼓励使用公共方法(getter/setter)来控制对私有字段的访问,便于未来修改内部实现而不影响外部接口。
  • 语法提示:编辑器和IDE通常会根据井号标记来提示哪些字段是私有的,帮助开发者遵循最佳实践。

虽然私有字段提高了封装性,但在设计API时,应谨慎考虑哪些数据应该设为私有,以平衡封装与灵活性的需求。


🔐 私有方法 (Private Methods)

私有方法是ES2020引入的另一项关键特性,与私有字段类似,它们通过在方法名前添加#符号来定义,以此增强类的封装性并保护类的内部实现细节不被外部访问或篡改。

class Calculator {// 声明一个私有方法 #multiply#multiply(a, b) {// 实现乘法逻辑return a * b;}/*** 公共方法,计算两个数的乘积* @param {number} a - 第一个乘数* @param {number} b - 第二个乘数* @returns {number} 两数的乘积*/calculateProduct(a, b) {// 内部可以无障碍访问私有方法 #multiplyreturn this.#multiply(a, b);}
}// 创建Calculator类的实例
const calc = new Calculator();// 通过公共方法间接调用私有方法,得到正确结果
console.log(calc.calculateProduct(2, 3)); // 输出: 6// 尝试直接访问或调用私有方法会导致语法错误
// console.log(calc.#multiply(2, 3)); // 这是不允许的,会导致编译或运行时错误
  • 封装性:私有方法隐藏了类的内部计算逻辑,只暴露必要的公共接口,符合面向对象设计的封装原则。
  • 安全性:防止外部代码直接调用或修改私有方法,减少潜在错误和安全风险。
  • 设计模式:鼓励使用面向接口而非实现编程,增强代码的灵活性和可测试性。
  • 代码提示:现代IDE能够识别出私有方法,给予开发者明确的视觉提示,减少误操作。

私有方法是JavaScript类中一种强大的工具,它帮助开发者构建更加健壮、安全和易于维护的代码库。正确使用私有方法,是提升代码质量和团队协作效率的关键之一。


🧬 继承 (Inheritance)

JavaScript中的类支持继承,使用 extends 关键字来实现。子类可以继承父类的属性和方法,并可覆盖或扩展它们。

class Animal { // 父类或基类constructor(name) {this.name = name; // 初始化属性}// 定义一个方法speak() {console.log(`${this.name} makes a noise.`);}
}class Dog extends Animal { // 子类或派生类,使用extends继承Animalconstructor(name) {super(name); // 调用父类构造函数,传递参数}// 重写父类的speak方法以适应Dog类的特性speak() {console.log(`${this.name} barks.`);}
}const myDog = new Dog('Rex'); // 创建Dog类的实例
myDog.speak(); // 输出: Rex barks.
  • extends关键字:用于创建一个类作为另一个类的子类,继承其所有非私有属性和方法。
  • super关键字:在子类构造函数中调用,用于访问父类的构造函数。这对于正确初始化继承自父类的属性至关重要。
  • 方法重写:子类可以定义与父类同名的方法,从而实现方法的覆盖(重写),根据子类的特点定制功能。
  • 访问控制与继承:父类的公有和受保护成员(没有使用#声明的)可以被子类继承和访问,私有成员则不能直接访问。
  • 多级继承:JavaScript支持多级继承,即一个子类可以再被其他类继承,形成继承链。

高级议题

  • Mixins与多重继承替代方案:由于JavaScript不直接支持多重继承,开发者可以利用组合、 Mixins模式或使用类的静态方法来模拟多重继承的效果。
  • 抽象类与接口概念:虽然JavaScript原生不支持抽象类和接口,但可以通过设计模式和约定来模仿这些概念,指导类的设计与实现。

通过继承机制,JavaScript的类体系能够构建层次清晰、复用性强的代码结构,是面向对象编程中不可或缺的一部分。


📦 静态方法与属性 (Static Methods and Properties)

静态方法和属性是类的一部分,它们不依赖于类的实例,可以直接通过类名访问。这使得静态成员成为执行与类的实例无关操作的理想选择,比如工具函数或常量值。在JavaScript中,使用static关键字来定义静态成员。

静态方法

  • 定义:静态方法是与类关联而非与类的实例关联的方法。它们通常用于执行与类的实例无关的操作,比如实用函数。
  • 访问:通过类名直接调用,无须创建类的实例。
  • 示例:在MathUtil类中,add是一个静态方法,用于执行简单的加法运算,不依赖于任何特定实例的状态。

静态属性

  • 定义:静态属性是类级别的变量,所有类的实例共享同一份数据。它们通常用于存储类的常量值或配置信息。
  • 初始化:静态属性可以在类定义中直接赋值,或者使用类的静态初始化块(ES2022引入)进行更复杂的初始化逻辑。
  • 示例PI是一个静态属性,存储圆周率的近似值,对所有MathUtil的调用者都是一致的。

示例代码

class MathUtil {// 静态属性定义,存储π的值static PI = 3.14159;// 静态方法定义,实现两个数的相加static add(a, b) {return a + b;}
}// 直接通过类名调用静态方法和属性
console.log(MathUtil.add(2, 3)); // 输出: 5
console.log(MathUtil.PI); // 输出: 3.14159// 注意:静态成员不能通过类的实例访问
// const util = new MathUtil();
// util.add(2, 3); // 这是不推荐的,尽管技术上可行,但违反了静态方法的使用原则
  • 共享性:静态方法和属性对于类的所有实例都是共享的,修改它们会影响所有实例。
  • 内存占用:每个静态成员只占用一份内存空间,不同于实例成员每个实例都会有一份。
  • 设计原则:静态成员适合于那些与类的状态无关,仅需通过类本身访问的功能或数据。
  • 访问限制:静态成员不能通过实例访问,这是保持设计清晰和减少误用的一种方式。

综上所述,静态方法和属性为JavaScript类的设计提供了额外的灵活性和功能,特别适用于那些全局工具函数或类级常量的场景。正确使用静态成员,可以使代码更加整洁高效。


🔄 Getter 和 Setter 解析

Getter和Setter是JavaScript类中用于定义访问和修改对象属性的特殊方法,它们为属性访问提供了额外的控制层,允许在获取或设置属性值时执行自定义逻辑,如数据验证、格式化或触发副作用。这种机制被称为“访问器属性”。

基本概念

  • Getter:用于读取属性值。定义时使用get关键字,无参数,返回属性值。
  • Setter:用于设置属性值。定义时使用set关键字,有一个参数(通常是新值),用于更新属性。

示例代码分析

class Product {constructor(price) {// 使用下划线前缀是一种约定,表示这个属性应该是“受保护”的或内部使用的this._price = price;}// Getter方法,获取价格get price() {return this._price;}// Setter方法,设置价格,包含验证逻辑set price(newValue) {// 验证价格是否为正数if (newValue < 0) {throw new Error('Price cannot be negative');}// 通过验证后,更新价格this._price = newValue;}
}// 创建Product实例
const product = new Product(10);// 使用getter读取价格
console.log(product.price); // 输出: 10// 尝试使用setter设置负价格,这将触发错误
try {product.price = -5;
} catch (error) {console.error(error.message); // 输出: Price cannot be negative
}

重要用途

  1. 数据验证:在setter中添加条件检查,确保数据的合法性,如上述示例中确保价格非负。
  2. 属性转换:在getter或setter中转换数据格式,例如,将内部存储的日期转换为字符串输出。
  3. 触发事件:当属性值改变时,可以在setter内部触发自定义事件或执行其他操作。
  4. 封装实现:隐藏属性的实际存储方式或逻辑,提供简洁的公共接口。

注意事项

  • Getter和Setter应成对出现,以便提供一致的访问控制机制。
  • 使用下划线前缀(如_price)是一种常见的做法,用于区分私有或受保护的属性,但JavaScript本身并不强制私有性。
  • 从ES6开始,可以使用私有字段(如#price)来实现更严格的封装,但请注意,私有字段不能直接定义getter和setter。

通过getter和setter,开发者可以灵活地管理对象状态,增强代码的健壮性和可维护性,是实现面向对象设计中封装原则的有效手段。


📚 总结

在JavaScript中,class语法作为一种面向对象编程的结构化方式,为创建可复用、易于维护的代码提供了强大支持。

  1. 构造函数 (Constructor):

    • 负责初始化新创建的类实例,自动在使用new关键字实例化时调用。
    • 可以接收参数并使用this关键字为实例分配属性。
    • 是类定义中的核心入口点,奠定了实例的基础状态。
  2. 私有字段与方法 (Private Fields & Methods):

    • ES2022 引入了私有字段与方法,通过在名称前加#来声明,增强了类的封装性。
    • 私有字段和方法仅能在类内部访问,外部代码无法直接触及,确保了数据安全和实现细节的隐藏。
    • 促进良好的封装实践,限制了对内部状态的不当修改。
  3. 继承 (Inheritance):

    • 使用extends关键字实现类的继承,子类能继承父类的属性和方法。
    • super关键字允许子类调用父类的构造函数和方法,支持方法覆盖以实现具体化或优化。
    • 构建类的层次结构,促进代码复用和模块化设计。
  4. 静态方法与属性 (Static Methods and Properties):

    • 通过static关键字定义,直接通过类名访问,不依赖于类的实例。
    • 适用于类级别操作和常量数据,如工具函数和配置项。
    • 提高代码组织性和效率,避免了每次实例化时的资源消耗。
  5. Getter和Setter:

    • 提供了一种控制属性访问和修改的机制,增加逻辑验证和灵活性。
    • Getter用于获取属性值,Setter用于设置属性值,并可嵌入验证逻辑。
    • 有助于实现数据验证、格式化和封装,保持数据一致性与安全。

综上所述,JavaScript的class语法通过构造函数、私有特性、继承机制、静态成员以及getter和setter,为开发者提供了一套完整的面向对象编程工具集,支持构建复杂而结构化的应用程序。这些特性不仅提升了代码的可读性和可维护性,也促进了面向对象设计原则在JavaScript中的应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/6374.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLO自研模块:多尺度轻量化卷积模块

目录 一、原理 二、代码 三、配置文件 一、原理 不同大小的卷积核,提取目标特征的特征尺度不同,所以通过使用不同大小卷积核的卷积来提取特征就可以保证获取到目标的多尺度特征。 借鉴YOLOv8中,将通道数进行划分的操作,在卷积的输入过程中为了减小参数量,将输入通道数…

计算机的翻译(编译和链接)过程

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;C语言基本概念 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 &#x1f697;1.翻译环境和运行环境&#xff1…

生信小知识 | 如何快速确定一个物种某一个基因家族全部基因数目

公众号&#xff1a;生信漫谈&#xff0c;获取最新科研信息&#xff01; 生信小知识 | 如何快速确定一个物种某一个基因家族全部基因数目https://mp.weixin.qq.com/s?__bizMzkwNjQyNTUwMw&mid2247486827&idx1&sn9fea85f8d28af3e02570235936a1f535&chksmc0e9e8…

io流,字节流概述

io流概述 io流&#xff1a;输入输出流读写数据的 i 指Input&#xff0c;称为输入流:负责把数据读到内存中去 o指Output&#xff0c;称为输出流:负责写数据出去 io流的分类 按流的方向分为: 输入流和输出流。 按流中数据的最小单位&#xff0c; 分为:字节流&#xff08;适合操作…

展开说说:Android Fragment完全解析-卷三

本文章分析了Fragment的管理器FragmentManager、事务FragmentTransaction 、以及完整的声明周期和动态加载Fragment的原理解析。 1、Fragment管理器 FragmentManager 类负责在应用的 fragment 上执行一些操作&#xff0c;如添加、移除或替换操作&#xff0c;以及将操作添加到…

c#学习基础2

四、复杂数据类型--结构体 1.基本概念 、2.基本语法 结构体一般写在namespace语句块中&#xff1b; 结构体关键字 struct 3.实例 4.结构体的使用 5.访问修饰符 6.结构体的构造函数 7.总结 五、排序初探 1&#xff09;冒泡排序 1.排序的基本概念 2.冒泡排序的基本原理 两…

西班牙语语法名词的复数形式,柯桥西班牙语培训

&#xff08;2&#xff09;后面加-es • 以辅音结尾的名词。例如&#xff1a; el seor - los seores 先生 la ciudad - las ciudades 城市 • 以-y 结尾的名词。例如&#xff1a; el rey - los reyes 国王 la ley - las leyes 法律 • 以-z 结尾的名词&#xff0c;将词尾…

【Linux】学习笔记

文章目录 [toc]第一章&#xff1a;基础篇01|课程介绍02|内容综述03|什么是Linux04|Linux的内核版本及常见发行版内核版本发行版本Red Hat Enterprise LinuxFedoraCentOSDebianUbuntu 05|安装VirtualBox虚拟机VirtualBox下载url 06|在虚拟机中安装Linux系统Linux安装镜像下载 07…

数据库(MySQL)—— 多表查询

数据库&#xff08;MySQL&#xff09;—— 多表查询 多表关系一对多多对多一对一多表查询概述数据准备查询形式笛卡尔积 分类连接查询内连接外连接左外连接右外连接 自连接联合查询 今天我们来进入MySQL中一个非常重要的部分&#xff1a;多表查询&#xff1a; 多表关系 多表关…

从零开始学AI绘画,万字Stable Diffusion终极教程(四)

【第4期】图生图 欢迎来到SD的终极教程&#xff0c;这是我们的第四节课 这套课程分为六节课&#xff0c;会系统性的介绍sd的全部功能&#xff0c;让你打下坚实牢靠的基础 1.SD入门 2.关键词 3.Lora模型 4.图生图 5.controlnet 6.知识补充 在前面的课程中&#xff0c;我…

主机win10,VMware 装了ubuntu,ubuntu传文件到主机

亲测可用&#xff0c;1分钟搞定&#xff0c;不能用你打死我 使用 FileZilla 工具互传 FileZilla是一款免费的工具&#xff0c;是基于 FTP 协议进行文件互传的&#xff0c;在传输过程中我们的ubuntu是作为服务器&#xff0c; FileZilla 工具则是作为客户端。 1 ubuntu安装 FTP…

【力扣】203、环形链表 II

142. 环形链表 II 要解决这道题&#xff0c;首先需要对问题进行拆解&#xff1a; 确定链表是否存在环确定环的入口点 如何判断是否存在环呢&#xff1f;这个比较容易想到&#xff0c;使用快慢指针即可判断链表是否存在环。我们定义两个指针&#xff1a; ListNode slow head…

容器组_配置初始化容器

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d8;相关专栏Rust初阶教程、go语言基础系列、spring教程等&#xff0c;大家有兴趣的可以看一看 &#x1f4d9;Jav…

SSM整合-前后端分离-项目环境搭建 (上)

整合SSM 项目基础环境搭建项目介绍创建项目项目全局配置web.xmlSpringMVC配置配置Spring和MyBatis, 并完成整合创建表, 使用逆向工程生成Bean, XxxMapper和XxxMapper.xml注意事项和细节说明 实现功能01-搭建Vue前端工程需求分析/图解代码实现搭建Vue前端工程vue3项目目录结构梳…

服务网关GateWay原理

文章目录 自动装配核心类GatewayAutoConfigurationDispatcherHandler请求处理阶段apply方法httpHandler#handle方法WebHandler#handle方法DispatchHanlder#handle方法第一步 getHandler获取请求映射第二步 invokeHandler 请求适配第三步 handleResult请求处理总结 上一篇博文我…

Gitea 上传用户签名

在 Gitea 的用户管理部分&#xff0c;有一个 SSH 和 GPG 的选项。 单击这个选项&#xff0c;可以在选项上添加 Key。 Key 的来源 如是 Windows 的用户&#xff0c;可以选择 Kleopatra 这个软件。 通过这个软件生成的 Key 的界面中有一个导出功能。 单击这个导出&#xff0c;…

OpenWRT有线桥接部署教程

前言 之前咱们讲到OpenWRT部署WAN实现PPPoE拨号上网和自动获取IP模式上网的办法&#xff1a; OpenWRT设置PPPoE拨号教程 OpenWRT设置自动获取IP&#xff0c;作为二级路由器 这一次&#xff0c;咱们尝试用OpenWRT有线桥接上一级路由器的教程。 可能有小伙伴敏锐地发现了&am…

【JVM】GC调优(优化JVM参数)、性能调优

GC调优 GC调优的主要目标是避免由垃圾回收引起程序性能下降。 GC调优的核心指标 垃圾回收吞吐量&#xff1a;执行用户代码时间/&#xff08;执行用户代码时间 GC时间&#xff09;延迟&#xff1a;GC延迟 业务执行时间内存使用量 GC调优步骤 发现问题&#xff1a;通过监控…

论文研读|针对文生图模型的AIGC检测

前言&#xff1a;人工智能生成内容的鉴别&#xff08;AIGC检测&#xff09;算是当前的研究热点之一&#xff0c;本篇文章介绍几篇针对文生图模型的 AIGC 检测相关工作。 相关文章&#xff1a;AIGC溯源相关研究详见此篇文章 目录 1. Towards Universal Fake Image Detectors tha…

OneNote导出白色背景文件时将笔记墨迹转换颜色

今天用OneNote导出笔记时发现在文件上做的黑色墨迹笔记全部转成了白色。推测是因为onenote会根据背景色自动转换黑色和白色的墨迹&#xff0c;但是其他颜色好像导出的时候不会转换。 于是&#xff0c;我们首先要转换背景&#xff0c;将黑色背景转成白色背景&#xff0c; 然后将…