首页/文章/javascript

JS进阶 | 详解ES6中的Class

2023-12-19
19047 分钟
...

「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战

JS进阶系列文章

👇 阅读本文你将学习到 👇

  • 类中的构造函数
  • 类的实例、静态、私有属性
  • 类的实例、静态、私有方法
  • 类的继承
  • Getter and Setter
  • 关于class一些扩展知识点

ES6ECMAScript6)之前,JavaScript语法中是不支持类的,导致面向对象编程方法无法直接使用,但我们可以通过function来实现模拟出类,而随着JavaScript的更新,在ES6出现了中出现class关键字,可以用于定义类。接下来让我们看看它的如何使用的。

class

下面我们来看看如何使用class关键字声明一个类。

class Animal {

}



const Animal = class {

}

而在ES6之前,我们都是通过以下这样子的方式来模拟出类的。

function Animal(){

}

类的构造函数

每一个类都可以有一个自己的构造函数,这个名称是固定的constructor,当我们通过new调用一个类时,这个类就会调用自己的constructor方法(构造函数)。

  • 它用于创建对象时给类传递一些参数
  • 每一个类只能有一个构造函数,否则报错

通过new调用一个类时,会调用构造函数,执行如下操作过程:

  1. 在内存中开辟一块新的空间用于创建新的对象
  2. 这个对象内部的__proto__属性会被赋值为该类的prototype属性
  3. 构造函数内的this,指向创建出来的新对象
  4. 执行构造函数的内部代码
  5. 如果函数没有返回对象,则返回this
class Animal  {
  
  
  constructor(name) {
    this.name = name;
  }
}

var a = new Animal("ABC");
console.log(a); 

上面这个例子中,我们在class中定义的constructor,这个就是构造方法,而this代表的是实例对象。

这个class,你可以把它看作构造函数的另外一种写法,因为它和它的构造函数的相等的,即是类本身指向构造函数。

console.log(Animal === Animal.prototype.constructor); 

其实,在类上的所有方法都会放在prototype属性上。

类中的属性

实例属性

实例的属性必须定义在类的方法里,就如上面的例子,我们在构造函数中定义name这个属性。

class Animal{
  constructor(name,height,weight) {
    this.name = name;
    this.height = height
    this.weight = weight
  }
}

静态属性

当我们把一个属性赋值给类本身,而不是赋值给它prototype,这样子的属性被称之为静态属性(static)。

静态属性直接通过类来访问,无需在实例中访问。

class Foo{
  static name ='_island'
}

console.log(Foo.name);

私有属性

私有属性只能在类中读取、写入,不能通过外部引用私有字段。

class Animal{
  #age;
  constructor(name,age){
    this.name=name
    this.#age=age
  }
}

var a = new Animal('_island',18)
console.log(a); 
console.log(a.name); 
console.log(a.age); 
console.log(a.#age); 

我们通过getOwnPropertyDescriptors方法获取到它的属性,同样也是获取不到。

console.log(Object.getOwnPropertyDescriptors(a))

{
  name: {
    value: '_island',
    writable: true,
    enumerable: true,
    configurable: true
  }
}

私有字段仅能在字段声明中预先定义。

公共和私有字段声明是JavaScript标准委员会TC39提出的实验性功能(第3阶段)。浏览器中的支持是有限的,但是可以通过Babel等系统构建后使用此功能。

类中的方法

实例方法

ES6之前,我们定义类中的方法是类中的原型上进行定义的,防止类中的方法重复在多个对象上。

function Animal() {}
Animal.prototype.eating = function () {
  console.log(this.name + " eating");
};

ES6中,定义类中的方法更加简洁,直接在类中定义即可,这样子的写法即优雅可读性也强。

class Animal{
  eating() {
    console.log(this.name + " eating");
  }
}

静态方法

静态方法与上面提到的静态属性是一样的,在方法前面使用static关键字进行声明,之后调用这个方法时不需要通过类的实例来调用,可以直接通过类名来调用它。

class Animal{
  static createName(name) {
    return name
  }
}

var a2 = Animal.createName("_island");
console.log(a2); 

私有方法

在面向对象中,私有方法是一个常见需求,但是在ES6中没有提供,我们可以通过某个方法来实现它。

class Foo {
  __getBloodType() {
    return "O";
  }
}

需要注意的是,通过下划线开头通常我们会局限它是一个私有方法,但是在类的外部还是可以正常调用到这个方法的

类的继承

extends关键字用于扩展子类,创建一个类作为另外一个类的一个子类。

它会将父类中的属性和方法一起继承到子类的,减少子类中重复的业务代码。

这对比之前在ES5中修改原型链实现继承的方法的可读性要强很多,而且写法很简洁。

extends的使用

class Animal{

}


class dog extends Animal {

}

继承类的属性和方法

下面这个例子,我们定义了dog这个类,通过extends关键字继承了Animal类的属性和方法。

在子类的constructor方法中,我们使用了super关键字,在子类中它是必须存在的,否则新建实例时会抛出异常。这是因为子类的this对象是继承自父类的this对象,如果不调用super方法,子类就得不到this对象。

class Animal {
  constructor(name) {
    this.name = name;
  }
  eating() {
    console.log(this.name + " eating");
  }
}


class dog extends Animal {
  constructor(name, legs) {
    super(name);
    this.legs = legs;
  }
  speaking() {
    console.log(this.name + " speaking");
  }
}

var d = new dog("tom", 4);
d.eating(); 
d.speaking(); 
console.log(d.name); 

Super

super关键字用于访问和调用一个对象的父对象上的函数。

super指的是超级、顶级、父类的意思

在子类的构造函数中使用this或者返回默认对象之前,必须先通过super调用父类的构造函数。

下面这段代码,子类的constructor方法中先调用了super方法,它代表了父类的构造函数,也就是说我们把参数传递进去之后,其实它是调用了父类的构造函数。

class Animal{
  constructor(name)
}

class dog{
  constructor(name,type,weight){
    super(name)
    this.type=type
    this.weight=weight
  }
}

下面这段代码使用super调用父类的方法

class Animal {
  constructor(name) {
    this.name = name;
  }
  eating() {
    console.log(this.name + " eating");
  }
}


class dog extends Animal {
  constructor(name, legs) {
    super(name);
    this.legs = legs;
  }
  speaking() {
    super.eating()
    console.log(this.name + " speaking");
  }
  
}

var d = new dog("tom",4);
d.speaking(); 

Getter 和 Setter

在类内部也可以使用getset关键字,对应某个属性设置存值和取值函数,拦截属性的存取行为。

class Animal {
  constructor() {
    this._age = 3;
  }

  get age() {
    return this._age;
  }

  set age(val) {
    this._age = val;
  }
}

var a = new Animal();
console.log(a.age); 
a.age = 4;
console.log(a.age); 

关于class扩展

严格模式

在类和模块的内部,默认是严格模式,所以不需要使用use strict指定运行模式。只要你的代码写在类或模块之中,就只有严格模式可用。

name属性

ES6中的类只是ES5构造函数的一层包装,所以函数的许多属性都被class继承了,包括name属性。

class Animal{

}
console.log(Animal.name); 

变量提升

class不存在变量提升,这与我们在ES5中实现类的不同的,function关键字会存在变量提升。

new Foo(); 
class Foo {}

总结

ES6之后,我们在定义类以及它内部的属性方法,还有继承操作的语法变得非常简洁且易懂,class是一个语法糖,其内部还是通过ES5中的语法来实现的。且有些浏览器不支持class语法,我们可以通过babel来进行转换。

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
javascript2025-09-18
JavaScript 的多线程能力:Worker
如果你写过一些计算量稍大的 JavaScript 代码,比如图像处理、大量数据排序或者复杂的算法,你几乎肯定遇到过浏览器“卡死”的现象。点击页面没反应,动画也停了,就像整个世界都静止了。 这就是主线程被阻塞的典型后果。因为主线程既要负责执行 JavaScript,又要负责渲染页面、响应用户操作,一旦它被繁重的计算任务占满,就无暇顾及其他,用户体验便直线下降。 这个问题的根源,正是“主线程是单线程的”。那么,如何解决呢? 答案很简单:把这...
学习面试
javascript2025-09-10
手把手教你实现一个EventEmitter
你是不是也遇到过这种情况:代码里各种事件监听和触发,回调函数套了一层又一层,最后自己都理不清哪个事件先触发、哪个后触发了? 别担心,今天我就带你从零开始实现一个自己的事件触发器(EventEmitter),让你彻底掌握事件驱动的精髓,代码清晰度直接提升200%! 为什么要懂EventEmitter? 先说说为什么我们要关心这个。Node.js的核心就是事件驱动,比如文件读写、网络请求,都是通过事件来处理的。不会EventEmitter,...
学习面试
javascript2025-08-09
Web Worker 多线程魔法
你是否曾遇到过网页因为复杂计算而卡顿的情况?今天,让我们一起探索Web Worker的神奇世界,看看如何用多线程技术解决性能瓶颈,并实现流畅的图片压缩功能! 为什么需要Web Worker? 想象一下,你在一个繁忙的餐厅里,只有一位服务员(主线程)负责点餐、上菜、结账所有工作。当客人突然暴增时,这位服务员就会手忙脚乱,其他客人只能干等着… 这就是JavaScript的现状—— 单线程 !所有任务都在一个线程中排队执行,一旦遇到复杂计算(...
学习面试
javascript2025-08-07
🌐AST抽象语法树
AST 是前端开发中一个非常重要的概念,它就像是代码的“编译器”,能够帮助我们理解和操作代码。本文将深入探讨 AST 的原理和应用,带你从零开始了解 AST。 一、什么是 AST? AST(抽象语法树)是一种树形结构,用于表示程序代码的语法结构。它将代码分解为一系列的节点,每个节点代表代码中的一个元素,如变量、函数、表达式等。AST 是编译器和解释器的基础,也是代码分析和转换的关键工具。 1\. AST 的结构 AST 的结构通常包括以...
学习面试
javascript2025-08-05
打字机效果是如何实现的
分析效果 使用 AI 对话的时候,文字是一个字一个字蹦出来的?它不是等所有内容生成完毕后一次性展示,而是以一种流畅、实时的“打字机”效果呈现,这种体验的背后,隐藏着一种高效的Web技术。它就是 服务器推送事件(Server Sent Events,简称 SSE) 什么是 SSE 从根本上说,SSE 是一种允许服务器 单向 、 持续 地向客户端(浏览器)推送数据的Web技术。 可以把它想象成一个 电台广播 : 服务器 是广播电台,持续不断...
学习面试
javascript2025-08-04
Promise 从原理到实现
前言 是 异步编程的核心概念之一,它为我们提供了一种更优雅的方式来处理异步操作。 本文将全面剖析 的工作原理,并逐步实现一个符合 规范的 。 正文 一、Promise 基础概念 代表一个异步操作的最终完成(或失败)及其结果值。它有 种状态: 1. pending : ,既不是成功,也不是失败状态 2. fulfilled :意味着操作 完成 3. rejected :意味着操作 状态一旦改变就不能再变,只能从 变为 ,或从 变为 。 二...
学习面试

评论

请登录后发表评论

去登录
加载评论中...

目录