理解 JavaScript 中的类

2023-11-04

介绍

JavaScript 是一种基于原型的语言,JavaScript 中的每个对象都有一个隐藏的内部属性,称为[[Prototype]]可用于扩展对象属性和方法。您可以在我们的文章中阅读有关原型的更多信息了解 JavaScript 中的原型和继承教程。

直到最近,勤奋的开发人员还使用构造函数模仿 JavaScript 中的面向对象设计模式。语言规范 ECMAScript 2015(通常称为 ES6)向 JavaScript 语言引入了类。 JavaScript 中的类实际上并不提供额外的功能,并且通常被描述为在原型和继承之上提供“语法糖”,因为它们提供了更清晰、更优雅的语法。由于其他编程语言使用类,因此 JavaScript 中的类语法使开发人员可以更直接地在语言之间切换。

类就是函数

JavaScript 类是一种函数。类的声明是class关键词。我们将使用函数表达式语法来初始化函数,使用类表达式语法来初始化类。

// Initializing a function with a function expression
const x = function() {}
// Initializing a class with a class expression
const y = class {}

我们可以访问[[Prototype]]的对象使用Object.getPrototypeOf() method。让我们用它来测试空function我们创造了。

Object.getPrototypeOf(x);
Output
ƒ () { [native code] }

我们也可以使用该方法class我们刚刚创建。

Object.getPrototypeOf(y);
Output
ƒ () { [native code] }

声明的代码function and class两者都返回一个函数[[Prototype]]。通过原型,任何函数都可以使用以下方式成为构造函数实例new关键词。

const x = function() {}

// Initialize a constructor from a function
const constructorFromFunction = new x();

console.log(constructorFromFunction);
Output
x {} constructor: ƒ ()

这也适用于类。

const y = class {}

// Initialize a constructor from a class
const constructorFromClass = new y();

console.log(constructorFromClass);
Output
y {} constructor: class

这些原型构造函数示例是空的,但我们可以看到在语法之下,两种方法如何实现相同的最终结果。

定义一个类

In the 原型和继承教程,我们创建了一个基于文本角色扮演游戏中的角色创建的示例。让我们继续这里的示例,将语法从函数更新为类。

A 构造函数使用许多参数进行初始化,这些参数将被分配为属性this,指的是函数本身。按照惯例,标识符的第一个字母应大写。

构造函数.js
// Initializing a constructor function
function Hero(name, level) {
	this.name = name;
	this.level = level;
}

当我们把它翻译成class语法如下所示,我们看到它的结构非常相似。

class.js
// Initializing a class definition
class Hero {
	constructor(name, level) {
		this.name = name;
		this.level = level;
	}
}

我们知道构造函数应该是一个对象蓝图,通过初始化器的第一个字母的大写(这是可选的)并熟悉语法。这class关键字以更直接的方式传达我们功能的目标。

初始化语法的唯一区别是使用class关键字而不是function,并分配 a 内的属性constructor() method.

定义方法

构造函数的常见做法是将方法直接分配给prototype而不是在初始化中,如greet()方法如下。

构造函数.js
function Hero(name, level) {
	this.name = name;
	this.level = level;
}

// Adding a method to the constructor
Hero.prototype.greet = function() {
	return `${this.name} says hello.`;
}

对于类,这种语法得到了简化,并且可以将方法直接添加到类中。使用方法定义简写ES6 中引入,定义方法是一个更加简洁的过程。

class.js
class Hero {
	constructor(name, level) {
		this.name = name;
		this.level = level;
	}

	// Adding a method to the constructor
	greet() {
		return `${this.name} says hello.`;
    }
}

让我们看看这些属性和方法的实际应用。我们将创建一个新实例Hero使用new关键字,并分配一些值。

const hero1 = new Hero('Varg', 1);

如果我们打印出有关新对象的更多信息console.log(hero1),我们可以看到有关类初始化所发生情况的更多详细信息。

Output
Hero {name: "Varg", level: 1} __proto__: ▶ constructor: class Hero ▶ greet: ƒ greet()

我们可以在输出中看到constructor() and greet()函数被应用到__proto__, or [[Prototype]] of hero1,而不是直接作为方法hero1目的。虽然在创建构造函数时这一点很明显,但在创建类时却并不明显。类允许更简单和简洁的语法,但在过程中牺牲了一些清晰度。

扩展一个类

构造函数和类的一个有利特征是它们可以扩展到基于父对象的新对象蓝图。这可以防止类似但需要一些附加或更具体功能的对象重复代码。

可以使用父级创建新的构造函数call()方法。在下面的示例中,我们将创建一个更具体的字符类,称为Mage,并分配属性Hero对其使用call(),以及添加额外的属性。

构造函数.js
// Creating a new constructor from the parent
function Mage(name, level, spell) {
	// Chain constructor with call
	Hero.call(this, name, level);

	this.spell = spell;
}

此时,我们可以创建一个新的实例Mage使用相同的属性Hero以及我们添加的一个新的。

const hero2 = new Mage('Lejon', 2, 'Magic Missile');

Sending hero2到控制台,我们可以看到我们已经创建了一个新的Mage基于构造函数。

Output
Mage {name: "Lejon", level: 2, spell: "Magic Missile"} __proto__: ▶ constructor: ƒ Mage(name, level, spell)

对于 ES6 类,super使用关键字代替call访问父函数。我们将使用extends来引用父类。

class.js
// Creating a new class from the parent
class Mage extends Hero {
	constructor(name, level, spell) {
		// Chain constructor with super
		super(name, level);

		// Add a new property
		this.spell = spell;
	}
}

现在我们可以创建一个新的Mage以同样的方式实例。

const hero2 = new Mage('Lejon', 2, 'Magic Missile');

我们将打印hero2到控制台并查看输出。

Output
Mage {name: "Lejon", level: 2, spell: "Magic Missile"} __proto__: Hero ▶ constructor: class Mage

输出几乎完全相同,除了在类构造中[[Prototype]]链接到父级,在本例中Hero.

下面是构造函数和类的初始化、添加方法和继承的整个过程的并排比较。

构造函数.js
function Hero(name, level) {
	this.name = name;
	this.level = level;
}

// Adding a method to the constructor
Hero.prototype.greet = function() {
	return `${this.name} says hello.`;
}

// Creating a new constructor from the parent
function Mage(name, level, spell) {
	// Chain constructor with call
	Hero.call(this, name, level);

	this.spell = spell;
}
class.js
// Initializing a class
class Hero {
	constructor(name, level) {
		this.name = name;
		this.level = level;
	}

	// Adding a method to the constructor
	greet() {
		return `${this.name} says hello.`;
    }
}

// Creating a new class from the parent
class Mage extends Hero {
	constructor(name, level, spell) {
		// Chain constructor with super
		super(name, level);

		// Add a new property
		this.spell = spell;
	}
}

尽管语法完全不同,但这两种方法之间的基本结果几乎相同。类为我们提供了一种更简洁的创建对象蓝图的方法,而构造函数更准确地描述了幕后发生的事情。

结论

在本教程中,我们了解了 JavaScript 构造函数和 ES6 类之间的异同。类和构造函数都模仿 JavaScript 的面向对象继承模型,JavaScript 是一种基于原型的继承语言。

了解原型继承对于成为一名高效的 JavaScript 开发人员至关重要。熟悉类非常有帮助,因为流行的 JavaScript 库如React经常使用class syntax.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

理解 JavaScript 中的类 的相关文章

随机推荐

  • 在 Linux 上创建可启动 Debian 10 USB 记忆棒

    本教程解释了如何使用以下命令从 Linux 终端创建可启动的 Debian 10 Buster USB 记忆棒dd命令 USB 记忆棒可用于在任何支持从 USB 启动的计算机上启动和安装 Debian 先决条件 1GB 或更大的 USB 记
  • Linux 中的 sudo 命令

    sudo 命令允许您以另一个用户 默认为 root 用户 运行程序 如果您在命令行上花费大量时间 那么 sudo 是您经常使用的命令之一 使用 sudo 而不是以 root 身份登录更安全 因为您可以向单个用户授予有限的管理权限 而无需他们
  • 如何在 Ubuntu 18.04 上设置 Nginx 服务器块

    Nginx Server Blocks 允许您在一台机器上运行多个网站 使用服务器块 您可以指定站点文档根 包含网站文件的目录 为每个站点创建单独的安全策略 为每个站点使用不同的 SSL 证书等等 在本文中 我们将提供有关如何在 Ubunt
  • 如何在 CentOS 7 上使用 Nginx 安装 WordPress

    WordPress 是全球最受欢迎的开源博客和 CMS 平台 为当今互联网上四分之一的网站提供支持 它基于 PHP 和 MySQL 并包含大量可以通过免费和高级插件和主题进行扩展的功能 WordPress 是创建在线商店 网站或博客的最简单
  • 如何在 CentOS 7 上安装 OpenCV

    OpenCV 开源计算机视觉库 是一个开源计算机视觉库 绑定了 C Python 和 Java 并支持所有主要操作系统 它可以利用多核处理并具有 GPU 加速功能来实现实时操作 OpenCV 的应用非常广泛 包括医学图像分析 拼接街景图像
  • 您应该了解的 Apache 命令

    Apache HTTP 服务器是世界上最流行的 Web 服务器 它是一个免费 开源 跨平台的 HTTP 服务器 提供强大的功能 可以通过各种模块进行扩展 如果您是开发人员或系统管理员 您很可能经常与 Apache 打交道 在本指南中 我们将
  • 如何在 Debian 10 Linux 上安装和使用 Docker

    Docker 是一个容器化平台 允许您快速构建 测试和部署应用程序作为可移植 自给自足的容器 几乎可以在任何地方运行 在本教程中 我们将解释如何在 Debian 10 Buster 上安装 Docker 并探索基本的 Docker 概念和命
  • Linux 中的 W 命令

    在这篇文章中 我们将讨论w命令 w是一个命令行实用程序 显示有关当前登录用户以及每个用户正在执行的操作的信息 它还提供有关系统已运行多长时间 当前时间和系统平均负载的信息 如何使用w命令 语法为w命令如下 w OPTIONS USER Wh
  • 如何在 CentOS 7 上安装 Skype

    Skype是世界上最受欢迎的通信应用程序之一 可让您免费进行在线音频和视频通话 并以经济实惠的价格拨打全球手机和固定电话 Skype 不是开源应用程序 也不包含在 CentOS 存储库中 本教程介绍如何在 CentOS 7 上安装最新版本的
  • 如何在 Ubuntu 18.04 上设置 OpenVPN 服务器

    无论您是想在连接不可信的公共 Wi Fi 网络时安全可靠地访问互联网 绕过地理限制内容还是允许您的同事在远程工作时安全地连接到您的公司网络 使用 VPN 都是最佳解决方案 VPN 允许您连接到远程 VPN 服务器 使您的连接加密且安全 并通
  • Android布局-LinearLayout、RelativeLayout

    在本教程中 我们将概述 Android 布局 我们还将探索一些可用于组织屏幕内容的特定布局控件 即 Android LinearLayout 和 AndroidrelativeLayout 安卓布局 用户界面的基本构建块是View从 Vie
  • Python 文件操作 - 使用 Python 读取和写入文件

    在本教程中 我们将研究 Python 中的不同文件操作 我们将介绍如何使用 Python 读取文件 写入文件 删除文件等等 所以 事不宜迟 让我们开始吧 在 Python 中处理文件 在之前的教程中 我们使用了控制台接受输入 现在 我们将使
  • 如何在 JavaScript 中编写条件语句

    介绍 在编程中 很多时候您会希望根据用户输入或其他因素运行不同的代码块 例如 如果每个字段都正确填写 您可能希望提交表单 但如果缺少某些必填字段 您可能希望阻止该表单提交 为了完成这样的任务 我们有条件语句 它们是所有编程语言的组成部分 条
  • 如何在 CentOS 7 上使用 Apache 作为带有 mod_proxy 的反向代理

    介绍 A 反向代理是一种代理服务器 它接受 HTTP S 请求并将其透明地分发到一个或多个后端服务器 反向代理非常有用 因为许多现代 Web 应用程序使用后端应用程序服务器处理传入的 HTTP 请求 这些服务器并不意味着用户可以直接访问 并
  • 如何在 Ubuntu 16.04 上安装和配置 Elasticsearch

    介绍 弹性搜索是一个实时分布式搜索和分析数据的平台 它的流行是由于它的易用性 强大的功能和可扩展性 Elasticsearch 支持 RESTful 操作 这意味着您可以将 HTTP 方法 GET POST PUT DELETE 等 与 H
  • 如何在 CentOS 7 上使用 Let's Encrypt 保护 Apache

    介绍 让我们加密是一个证书颁发机构 CA 为以下用户提供免费证书传输层安全 TLS 加密 从而在 Web 服务器上启用加密的 HTTPS 它通过提供可自动执行大部分步骤的软件客户端 简化了证书的创建 验证 签名 安装和续订过程 Certbo
  • 如何在 Ubuntu 12.04 LTS(精确穿山甲)上安装 nginx

    Status 已弃用 本文介绍不再受支持的 Ubuntu 版本 如果您当前运行的服务器运行 Ubuntu 12 04 我们强烈建议您升级或迁移到受支持的 Ubuntu 版本 升级到Ubuntu 14 04 从 Ubuntu 14 04 升级
  • R 中的 head() 和 tail() 函数 - 详细参考

    The R 中的 head 和 tail 函数通常用于读取数据集的前 n 行和后 n 行 您可能是一名在职专业人员 程序员或新手 但有时您需要阅读大型数据集并对其进行分析 消化一个拥有 20 多列甚至更多列 数千行的庞大数据集确实很困难 本
  • NoSQL 数据库管理系统和模型的比较

    介绍 当大多数人想到数据库时 他们通常会想到传统的关系数据库模型 其中涉及由行和列组成的表 虽然关系数据库管理系统仍然处理互联网上的大部分数据 但近年来 随着开发人员寻求解决关系模型局限性的方法 替代数据模型变得更加普遍 这些非关系数据库模
  • 理解 JavaScript 中的类

    介绍 JavaScript 是一种基于原型的语言 JavaScript 中的每个对象都有一个隐藏的内部属性 称为 Prototype 可用于扩展对象属性和方法 您可以在我们的文章中阅读有关原型的更多信息了解 JavaScript 中的原型和