前端深入理解JavaScript面向对象编程与Class

2023-09-14 18:30:00

 🎬 岸边的风:个人主页

 🔥 个人专栏 :《 VUE 》 《 javaScript 》

⛺️ 生活的理想,就是为了理想的生活 !

在这里插入图片描述

目录

引言

1. 什么是面向对象编程?

2. Class的基本概念

3. Class的语法

3.1 构造函数

3.2 属性

3.3 方法

3.4 方法的访问修饰符

4. 类的静态方法和属性

5. Getter和Setter方法

6. 类的私有属性和方法

7. 类的实例和构造函数

8. 类的继承

9. 类的封装

10. 类的多态

11. 结语


引言

随着JavaScript的发展,ECMAScript 6(ES6)引入了许多新的语言特性和语法糖,其中包括了面向对象编程的Class(类)机制。Class提供了一种更简洁、更直观的方式来定义对象和操作对象的行为。本文将介绍ES6中Class的概念、语法和特性,并通过示例代码来说明其实际应用。

1. 什么是面向对象编程?

面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它将程序中的对象作为基本单元,通过封装、继承和多态等机制来组织和管理代码。面向对象编程将现实世界中的实体抽象为代码中的对象,对象拥有自己的状态(属性)和行为(方法),并与其他对象进行交互。

面向对象编程有以下几个核心概念:

  • 封装(Encapsulation):将数据和操作数据的方法封装在一个对象中,使其成为一个独立的实体,外部无法直接访问对象的内部实现细节。
  • 继承(Inheritance):通过定义一个基类(父类),其他类可以继承该基类的属性和方法,并可以在此基础上进行扩展或覆盖。
  • 多态(Polymorphism):不同对象可以对相同的方法做出不同的响应,即同一个方法可以根据调用对象的不同而具有不同的行为。

面向对象编程的优势包括代码的可重用性、可维护性、扩展性和灵活性等。

2. Class的基本概念

在ES6之前,JavaScript中的对象和面向对象编程的概念相对比较模糊。ES6引入了Class机制,使得JavaScript可以更加直观地定义和使用类。Class是一种特殊的函数,通过Class关键字定义。Class中可以定义构造函数、属性和方法等。

一个简单的Class示例如下:

class Rectangle {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  area() {
    return this.width * this.height;
  }

  perimeter() {
    return 2 * (this.width + this.height);
  }
}

在上述示例中,我们定义了一个名为Rectangle的类,

它具有widthheight两个属性,以及area()perimeter()两个方法。通过Class定义的类可以通过实例化来创建具体的对象,并调用其属性和方法。

const rect = new Rectangle(5, 3);
console.log(rect.area());       // 输出:15
console.log(rect.perimeter());  // 输出:16

3. Class的语法

ES6中Class的语法相对简洁明了。一个Class可以包含构造函数、属性和方法等。下面介绍一些常用的语法规则:

3.1 构造函数

在Class中使用constructor关键字定义构造函数。构造函数用于创建对象时进行初始化操作,通过new关键字实例化类时会自动调用构造函数。

class Rectangle {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }
}

构造函数中的this关键字表示当前实例化的对象。

3.2 属性

在Class中可以定义各种属性。属性可以直接定义在Class的内部,也可以在构造函数中通过this关键字进行定义。

class Rectangle {
  width = 0;    // 直接定义属性
  height = 0;

  constructor(width, height) {
    this.width = width;    // 在构造函数中定义属性
    this.height = height;
  }
}

3.3 方法

在Class中定义的函数称为方法。可以直接在Class的内部定义方法,也可以使用ES6的简写形式。

class Rectangle {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  area() {            // 定义方法
    return this.width * this.height;
  }

  perimeter() {
    return 2 * (this.width + this.height);
  }
}

3.4 方法的访问修饰符

在Class中,可以使用访问修饰符来限制方法的访问权限。ES6中的Class默认所有方法都是公共的,可以被外部调用。但我们可以使用staticgetsetprivateprotected等修饰符来控制方法的访问。

  • static:定义静态方法,只能通过类本身调用,不能通过类的实例调用。
  • getset:定义属性的读取和设置方法,使用类似访问属性的语法进行调用。
  • private:定义私有方法,只能在类的内部被访问,外部无法访问。
  • protected:定义受保护方法,只能在类的内部和子类中被访问,外部无法访问。

class Rectangle {
  static description = 'This is a rectangle';  // 静态属性

  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  static createSquare(side) {     // 静态方法
    return new Rectangle(side, side);
  }



  get area() {           // Getter方法
    return this.width * this.height;
  }

  set area(value) {     // Setter方法
    this.width = Math.sqrt(value);
    this.height = Math.sqrt(value);
  }

  #privateMethod() {    // 私有方法
    console.log('This is a private method');
  }

  protectedMethod() {   // 受保护方法
    console.log('This is a protected method');
  }

  publicMethod() {      // 公共方法
    console.log('This is a public method');
    this.#privateMethod();
    this.protectedMethod();
  }
}

在上述示例中,我们定义了一个Square类,它继承自Rectangle类。通过super关键字调用父类的构造函数,确保父类的属性被正确初始化。子类可以新增或覆盖父类的方法。

const square = new Square(5);
console.log(square.area());       // 输出:25
console.log(square.perimeter());  // 输出:20

4. 类的静态方法和属性

静态方法和属性属于类本身,而不是类的实例。静态方法和属性可以通过类名直接访问,无需实例化类。

class MathUtil {
  static PI = 3.14159;    // 静态属性

  static square(number) {    // 静态方法
    return number * number;
  }
}

在上述示例中,我们定义了一个MathUtil类,它具有一个静态属性PI和一个静态方法square()。可以通过类名直接访问静态属性和方法。

console.log(MathUtil.PI);        // 输出:3.14159
console.log(MathUtil.square(5)); // 输出:25

5. Getter和Setter方法

Getter和Setter方法用于对类的属性进行读取和设置操作,可以通过类似访问属性的语法进行调用。

class Circle {
  constructor(radius) {
    this.radius = radius;
  }

  get diameter() {
    return 2 * this.radius;
  }

  set diameter(value) {
    this.radius = value / 2;
  }
}

在上述示例中,我们定义了一个Circle类,它具有一个属性radius。通过定义get diameter()方法和set diameter()方法,我们可以通过类似访问属性的方式来读取和设置直径(diameter)属性,而不需要直接访问radius属性。

const circle = new Circle(5);
console.log(circle.diameter);     //

 输出:10
circle.diameter = 12;
console.log(circle.radius);       // 输出:6

6. 类的私有属性和方法

在ES6中,可以使用#作为前缀来定义私有属性和方法。私有属性和方法只能在类的内部被访问,外部无法访问。

class Person {
  #name;   // 私有属性

  constructor(name) {
    this.#name = name;
  }

  #privateMethod() {   // 私有方法
    console.log('This is a private method');
  }

  publicMethod() {      // 公共方法
    console.log(`Hello, my name is ${this.#name}`);
    this.#privateMethod();
  }
}

在上述示例中,我们定义了一个Person类,它具有一个私有属性#name和一个私有方法#privateMethod()。私有属性和方法只能在类的内部访问。

const person = new Person('John');
person.publicMethod();   // 输出:Hello, my name is John
person.#name;            // 报错:SyntaxError: Private field '#name' must be declared in an enclosing class
person.#privateMethod(); // 报错:SyntaxError: Private field '#privateMethod' must be declared in an enclosing class

7. 类的实例和构造函数

在ES6中,类的实例通过new关键字进行创建,并自动调用类的构造函数进行初始化。

const rect = new Rectangle(5, 3);
console.log(rect.area());       // 输出:15
console.log(rect.perimeter());  // 输出:16

可以使用instanceof运算符来判断一个对象是否是某个类的实例。

console.log(rect instanceof Rectangle);  // 输出:true
console.log(rect instanceof Object);     // 输出:true

8. 类的继承

继承是面向对象编程中的重要概念之一,它允许我们创建一个基类(父类),其他类可以继承该基类并扩展或覆盖其中的属性和方法。ES6中使用extends关键字实现类的继承。

class Square extends Rectangle {
  constructor(side) {
    super(side, side);    // 调用父类的构造函数
  }
}

9. 类的封装

封装通过将数据和操作数据的方法封装在一个对象中,实现了数据的保护和访问的控制。类的属性和方法可以使用不同的访问修饰符来控制其可见性。

class Rectangle {
  #width;  // 私有属性
  #height;

  constructor(width, height) {
    this.#width = width;
    this.#height = height;
  }

  getArea() {    // 公共方法
    return this.#width * this.#height;
  }
}

const rect = new Rectangle(5, 3);
console.log(rect.#width);  // 报错:SyntaxError: Private field '#width' must be declared in an enclosing class
console.log(rect.getArea());  // 输出:15

在上述示例中,Rectangle类具有私有属性#width和#height,只能在类的内部被访问。通过定义公共方法getArea()来访问私有属性,从而实现了封装。

10. 类的多态

多态允许不同的对象对相同的消息作出不同的响应。通过继承和方法的覆盖,不同的子类可以对父类的方法进行不同的实现,从而实现多态性。

class Animal {
  makeSound() {
    console.log('Animal makes sound');
  }
}

class Dog extends Animal {
  makeSound() {
    console.log('Dog barks');
  }
}

class Cat extends Animal {
  makeSound() {
    console.log('Cat meows');
  }
}

const animal = new Animal();
const dog = new Dog();
const cat = new Cat();

animal.makeSound();  // 输出:Animal makes sound
dog.makeSound();     // 输出:Dog barks
cat.makeSound();     // 输出:Cat meows

在上述示例中,Animal类是基类,Dog和Cat类是子类。它们都具有makeSound()方法,但不同的子类对该方法进行了不同的实现,实现了多态性。

通过封装、继承和多态,面向对象编程提供了一种更加灵活和可扩展的编程方式,使得代码的组织和管理更加直观和高效。

11. 结语

ES6引入的Class机制为JavaScript提供了一种更直观、更简洁的面向对象编程方式。通过Class,我们可以更方便地定义和使用类,实现封装、继承和多态等面向对象编程的基本原理。同时,ES6还提供了许多其他的语法糖和特性,使得JavaScript在面向对象编程方面更加强大和灵活。

更多推荐

基于微信小程序的校园失物招领系统设计与实现(源码+lw+部署文档+讲解等)

前言💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗👇🏻精彩专栏推荐订阅👇🏻2023-2024年最值得选的微信小程序毕业设计选题大全:100个热门选

手机技巧:推荐一款手机省电、提升流畅度APP

目录软件详情基本介绍软件功能软件特色使用方法软件对比结论今天给大家推荐一款手机省电、提升流畅度APP,感兴趣的朋友可以下载一下!软件详情黑阈app是一款非常实用的系统优化类手机APP。使用它能够禁止软件后台运行耗电,既能帮你省电还能守护手机安全。它对于阻止软件自启、互相唤醒有着非常明显的效果,可以显著提升安卓手机的续航

Java版本spring cloud + spring boot企业电子招投标系统源代码

项目说明随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及审计监督要求;通过电子化平台提高招投标工作的公开性和透明性;通过电子化招投标,使得招标采购的质量更高、速度

RUST 每日一省:全局变量

Rust中允许存在全局变量。它们一般有两种:常数和静态值。常量我们使用关键字const来创建常量。由于常量未使用关键字let声明,因此在创建它们时必须指定类型。常量只能进行简单赋值,并且没有固定的内存地址,无论它们在何处使用都会被内联。常量不能遮蔽,不能重复定义。也就是说,不存在内层或后面作用域定义的常量去遮蔽外层或前

RocketMQ 源码分析——Producer

文章目录消息发送代码实现消息发送者启动流程检查配置获得MQ客户端实例启动实例定时任务Producer消息发送流程选择队列默认选择队列策略故障延迟机制策略*两种策略的选择技术亮点:ThreadLocal消息发送代码实现下面是一个生产者发送消息的demo(同步发送)主要做了几件事:初始化一个生产者(DefaultMQPro

四、线性支持向量机算法(LinearSVC,Linear Support Vector Classification)(有监督学习)

线性支持向量机,LinearSupportVectorClassification.与参数内核为线性的SVC类似(SVC(kernel=‘linear’)),但使用liblinear而非libsvm实现,因此在选择惩罚和损失函数时更具灵活性,并能更好地扩展到大量样本SVC(kernel=’linear’)和Linear

Meta | 对比解码:进一步提升LLM推理能力

深度学习自然语言处理原创作者:wkk为了改进LLM的推理能力,UniversityofCalifornia联合MetaAI实验室提出将ContrastiveDecoding应用于多种任务的LLM方法。实验表明,所提方法能有效改进LLM的推理能力。让我们走进论文一探究竟吧!论文:ContrastiveDecodingIm

《动手学深度学习 Pytorch版》 6.1 从全连接层到卷积

6.1.1不变性平移不变性(translationinvariance):不管检测对象出现在图像中的哪个位置,神经网络的前面几层应该对相同的图像区域具有相似的反应,即为“平移不变性”。局部性(locality):神经网络的前面几层应该只探索输入图像中的局部区域,而不过度在意图像中相隔较远区域的关系,这就是“局部性”原则

《动手学深度学习 Pytorch版》 7.1 深度卷积神经网络(LeNet)

7.1.1学习表征深度卷积神经网络的突破出现在2012年。突破可归因于以下两个关键因素:缺少的成分:数据数据集紧缺的情况在2010年前后兴起的大数据浪潮中得到改善。ImageNet挑战赛中,ImageNet数据集由斯坦福大学教授李飞飞小组的研究人员开发,利用谷歌图像搜索对分类图片进行预筛选,并利用亚马逊众包标注每张图片

QT基础教程(文本绘制)

文章目录前言一、普通文本绘制二、绘制旋转文本三、旋转文本升级总结前言本篇文章我们来讲解一下QT中使用QPainter来绘制文本的案例。一、普通文本绘制在Qt中,你可以使用QPainter类来绘制文本,包括普通文本、格式化文本和自定义文本效果。下面是使用QPainter绘制文本的基本方法和示例:1.绘制普通文本:使用QP

Shiro【核心功能、核心组件、项目搭建 、配置文件认证、数据库认证 】(一)-全面详解(学习总结---从入门到深化)

目录Shiro介绍_Shiro核心功能Shiro介绍_Shiro核心组件Shiro入门_项目搭建Shiro入门_配置文件认证Shiro入门_数据库认证Shiro认证_将Shiro对象交给容器管理Shiro介绍_Shiro简介Shiro是apache旗下的一个开源安全框架,它可以帮助我们完成身份认证,授权、加密、会话管理

热文推荐