目录
钥匙要点
结论
> JavaScript中的“原型”是什么?在JavaScript中如何使用它在继承中?此属性是对另一个对象的原型对象的引用。创建函数时,其原型对象也会通过函数的原型属性创建并链接。当使用构造函数函数创建对象时,它从其构造函数的原型中继承了属性和方法。
javaScript不直接支持多个继承。但是,可以使用混合蛋白间接实现它。混合蛋白是一种涉及将属性从一个对象复制到另一个对象的技术。这允许对象从多个来源继承属性和方法。
>
首页 web前端 js教程 JavaScript ES2015中对象继承的模式

JavaScript ES2015中对象继承的模式

Feb 16, 2025 am 11:38 AM

JavaScript ES2015中对象继承的模式

钥匙要点

  • >使用ES2015,JavaScript现在具有专门定义类的语法,以保持代码清洁,最小化层次结构深度并避免重复代码。
  • >多重继承(由某些经典OOP语言支持的功能)允许创建从多个基类继承的类。但是,它遇到了钻石问题,其中两个父类定义了相同的方法。
  • 混合蛋白,仅包含方法的微小类是躲避钻石问题的另一种策略。 Mixins不用扩展这些类,而是在另一个类中包含。
  • >
  • >尽管班级语法给出了一种幻想,即JavaScript是一种基于类的OOP语言,但事实并非如此。大多数方法都需要修改对象的原型以模仿多重继承。使用类工厂功能是使用Mixins组成类的可接受策略。
  • JavaScript的
  • > ES2015(以前称为ES6)的已久的到来,配备了专门定义类的语法。在本文中,我将探讨是否可以利用类语法来撰写较小零件的类。
JavaScript ES2015中对象继承的模式>将层次深度保持在最低限度对于保持代码清洁很重要。对您如何拆分课程的方式很聪明。对于大型代码库,一种选择是创建较小零件的类。撰写课程。这也是避免重复代码的常见策略。

想象我们正在建立一个玩家生活在动物世界中的游戏。有些是朋友,有些是敌对的(像我这样的狗人可能会说所有猫都是敌对的生物)。我们可以创建一个hostileanimal,它可以扩展动物,以充当猫的基础。在某个时候,我们决定添加旨在伤害人类的机器人。我们要做的第一件事是创建机器人类。现在,我们有两个具有相似属性的类。例如,hostileanimal和机器人都可以攻击()。

>

>如果我们可以以某种方式在单独的类或对象中定义敌意,请说敌对,我们可以将其重用为CAT作为机器人。我们可以以各种方式做到这一点。

>多重继承

是某些经典的OOP语言支持的功能。顾名思义,它使我们能够创建一个从多个基类继承的类。查看CAT类在以下Python代码中如何扩展多个基类:>

and接口

是(键入)经典OOP语言中的常见功能。它允许我们定义类应包含的方法(有时是属性)。如果该课程没有,编译器将引起错误。如果CAT没有攻击()或walk()方法:>
<span>class Animal(object):
</span>  <span>def walk(self):
</span>    <span># ...
</span>
<span>class Hostile(object):
</span>  <span>def attack(self, target):
</span>    <span># ...
</span>
<span>class Dog(Animal):
</span>  <span># ...
</span>
<span>class Cat(Animal, Hostile):
</span>  <span># ...
</span>
dave <span>= Cat();
</span>dave<span>.walk();
</span>dave<span>.attack(target);
</span>
登录后复制
登录后复制
多个继承遭受钻石问题(其中两个父类定义相同的方法)。某些语言通过实施其他策略(例如)来避免此问题。 混合素是仅包含方法的小类。 Mixin并没有扩展这些课程,而是将Mixins包含在另一个类中。例如,在PHP中,使用特征实现Mixin。

a recap:es2015类语法

>如果您没有机会参加ES2015课程或觉得自己对它们的了解不足,请务必阅读Jeff Mott面向对象的JavaScript - 在继续之前深入研究ES6课程。 > 简而言之:
<span>interface Hostile {
</span>  <span>attack();
</span><span>}
</span>
<span>class Animal {
</span>  <span>walk();
</span><span>}
</span>
<span>class Dog extends Animal {
</span>  <span>// ...
</span><span>}
</span>
<span>class Cat extends Animal implements Hostile {
</span>  <span>attack() {
</span>    <span>// ...
</span>  <span>}
</span><span>}
</span>
登录后复制
登录后复制

>类foo {...}描述了一个名为foo

的类

类foo扩展bar {...}描述了一个foo的类,该类扩展了另一个类,bar

>

在类块中,我们可以定义该类的属性。在本文中,我们只需要了解构造函数和方法:
  • 构建器(){...}是一个保留函数,在创建时执行(new foo())>
  • > foo(){...}创建一个名为foo
  • 的方法

级语法主要是JavaScript原型模型上的句法糖。它不是创建类,而是创建一个函数构造函数:

>
  • 的要点是,JavaScript不是基于类的OOP语言。甚至可能认为语法是欺骗性的,给人的印象是。
  • 组成ES2015类
  • 可以通过创建一个抛出错误的虚拟方法来模仿
  • 接口。一旦继承,就必须覆盖该功能以避免错误:

如前所述,这种方法依赖于继承。要继承多个类,我们将需要多个继承或混合素。

<span>class Animal {
</span>  <span>// ...
</span><span>}
</span>
<span>trait Hostile {
</span>  <span>// ...
</span><span>}
</span>
<span>class Dog extends Animal {
</span>  <span>// ...
</span><span>}
</span>
<span>class Cat extends Animal {
</span>  <span>use Hostile;
</span>  <span>// ...
</span><span>}
</span>
<span>class Robot {
</span>  <span>use Hostile;
</span>  <span>// ...
</span><span>}
</span>
登录后复制
登录后复制
>另一种方法是编写一个实用程序函数,该函数在定义后验证类。可以在等待时找到一个例子,JavaScript确实支持多个继承!由Andrea Giammarchi。请参阅“基本对象”部分。

>探索应用多种继承和混合素的各种方法的时间。以下所有检查的策略均可在GitHub上获得。

>

object.assign(childclass.protype,mixin ...)

> ES2015前,我们使用原型来继承。所有功能都有一个原型属性。使用新的myFunction()创建实例时,将原型复制到实例中的属性。当您尝试访问不在实例的属性时,JavaScript引擎将尝试在原型对象中查找。

进行演示,请查看以下代码:
<span>class Foo {}
</span><span>console.log(typeof Foo); // "function"
</span>
登录后复制
登录后复制
>

可以在运行时创建和修改这些原型对象。最初,我试图将课程用于动物和敌对:

<span>class Animal(object):
</span>  <span>def walk(self):
</span>    <span># ...
</span>
<span>class Hostile(object):
</span>  <span>def attack(self, target):
</span>    <span># ...
</span>
<span>class Dog(Animal):
</span>  <span># ...
</span>
<span>class Cat(Animal, Hostile):
</span>  <span># ...
</span>
dave <span>= Cat();
</span>dave<span>.walk();
</span>dave<span>.attack(target);
</span>
登录后复制
登录后复制

上面的方法是不起作用的,因为类方法是>不枚举的。实际上,这意味着对象。分配(...)不从类复制方法。这也使得很难创建一个将方法从一个类复制到另一个类的函数。但是,我们可以手动复制每种方法:

>
<span>interface Hostile {
</span>  <span>attack();
</span><span>}
</span>
<span>class Animal {
</span>  <span>walk();
</span><span>}
</span>
<span>class Dog extends Animal {
</span>  <span>// ...
</span><span>}
</span>
<span>class Cat extends Animal implements Hostile {
</span>  <span>attack() {
</span>    <span>// ...
</span>  <span>}
</span><span>}
</span>
登录后复制
登录后复制

>另一种方法是抛弃类并使用对象作为混合物。积极的副作用是Mixin对象不能用于创建实例,以防止滥用。

<span>class Animal {
</span>  <span>// ...
</span><span>}
</span>
<span>trait Hostile {
</span>  <span>// ...
</span><span>}
</span>
<span>class Dog extends Animal {
</span>  <span>// ...
</span><span>}
</span>
<span>class Cat extends Animal {
</span>  <span>use Hostile;
</span>  <span>// ...
</span><span>}
</span>
<span>class Robot {
</span>  <span>use Hostile;
</span>  <span>// ...
</span><span>}
</span>
登录后复制
登录后复制
pros

    混合蛋白不能初始化
  • >
cons

需要额外的代码
  • object.assign()有点晦涩
  • 与ES2015类合作的重塑原型继承
  • 在构造函数中编写对象
  • >
>使用ES2015类,您可以通过在构造函数中返回对象来覆盖实例:

>我们可以利用该功能从子类内部的多个类中构成对象。请注意,object.sign(...)仍然与Mixin类无法正常工作,因此我在这里也使用了对象:>

<span>class Foo {}
</span><span>console.log(typeof Foo); // "function"
</span>
登录后复制
登录后复制
因为这是指在上下文中的类(使用不可算的方法),所以object.shassign(...,this)不复制cat的方法。相反,您必须在此上明确设置此字段和方法,以便object.Assign()能够应用这些字段和方法,例如:

>

<span>class IAnimal {
</span>  <span>walk() {
</span>    <span>throw new Error('Not implemented');
</span>  <span>}
</span><span>}
</span>
<span>class Dog extends IAnimal {
</span>  <span>// ...
</span><span>}
</span>
<span>const robbie = new Dog();
</span>robbie<span>.walk(); // Throws an error
</span>
登录后复制
这种方法是不切实际的。因为您要返回一个新对象而不是实例,所以它基本上等同于:>

我认为我们可以同意后者更可读。
<span>function <span>MyFunction</span> () {
</span>  <span>this.myOwnProperty = 1;
</span><span>}
</span><span>MyFunction.prototype.myProtoProperty = 2;
</span>
<span>const myInstance = new MyFunction();
</span>
<span>// logs "1"
</span><span>console.log(myInstance.myOwnProperty);
</span><span>// logs "2"
</span><span>console.log(myInstance.myProtoProperty);
</span>
<span>// logs "true", because "myOwnProperty" is a property of "myInstance"
</span><span>console.log(myInstance.hasOwnProperty('myOwnProperty'));
</span><span>// logs "false", because "myProtoProperty" isn’t a property of "myInstance", but "myInstance.__proto__"
</span><span>console.log(myInstance.hasOwnProperty('myProtoProperty'));
</span>
登录后复制
>

pros

<span>class Animal {
</span>  <span>walk() {
</span>    <span>// ...
</span>  <span>}
</span><span>}
</span>
<span>class Dog {
</span>  <span>// ...
</span><span>}
</span>
<span>Object.assign(Dog.prototype, Animal.prototype);
</span>
登录后复制

>它有效,我猜

>

cons
  • 非常模糊的
  • ES2015类语法
零收益

滥用ES2015类
  • 类工厂功能
  • 这种方法利用JavaScript在运行时定义类的能力。
  • 首先,我们需要基础类。在我们的例子中,动物和机器人充当基础类别。如果您想从头开始,一个空的班级也可以。
  • >
接下来,我们必须创建一个返回新类的工厂功能,该函数扩展了类基础,该类作为参数传递。这些是混合物:

>现在,我们可以将任何类传递给敌对功能,该函数将返回一个新的类,结合敌对的新类,以及我们传递给该功能的任何类:>

我们可以通过几个类进行管道应用多个混合素:

<span>Object.assign(Cat.prototype, {
</span>  <span>attack: Hostile.prototype.attack,
</span>  <span>walk: Animal.prototype.walk,
</span><span>});
</span>
登录后复制
您还可以将对象用作基类:

pros
<span>const Animal = {
</span>  <span>walk() {
</span>    <span>// ...
</span>  <span>},
</span><span>};
</span>
<span>const Hostile = {
</span>  <span>attack(target) {
</span>    <span>// ...
</span>  <span>},
</span><span>};
</span>
<span>class Cat {
</span>  <span>// ...
</span><span>}
</span>
<span>Object.assign(Cat.prototype, Animal, Hostile);
</span>
登录后复制

>更容易理解,因为所有信息都在类声明标题中
<span>class Answer {
</span>  <span>constructor(question) {
</span>    <span>return {
</span>      <span>answer: 42,
</span>    <span>};
</span>  <span>}
</span><span>}
</span>
<span>// { answer: 42 }
</span><span>new Answer("Life, the universe, and everything");
</span>
登录后复制

cons

  • 在运行时创建类可能会影响启动性能和/或内存使用

结论

>当我决定研究此主题并撰写有关它的文章时,我希望JavaScript的原型模型有助于生成课程。由于类语法使方法无法恢复,因此对象操纵变得更加困难,几乎不切实际。

类语法可能会产生幻想,即JavaScript是一种基于类的OOP语言,但事实并非如此。使用大多数方法,您将必须修改对象的原型以模仿多重继承。使用类工厂功能的最后一种方法是使用Mixins组成类的可接受策略。

>如果发现基于原型的编程限制性,则可能需要查看自己的心态。原型提供了无与伦比的灵活性。

如果出于任何原因,您仍然喜欢经典的编程,则可能需要研究编译为JavaScript的语言。例如,打字稿是JavaScript的超集,它添加了(可选的)静态键入和您将从其他经典OOP语言中识别的模式。>

您是否要在项目中使用上述两种方法?您找到了更好的方法吗?在评论中让我知道!

>

>本文是由杰夫·莫特(Jeff Mott),斯科特·莫利纳里(Scott Molinari),维尔丹·苏菲奇(Vildan Softic)和琼·元(Joan Yin)进行了审查。感谢SitePoint所有的同行评审器制作SitePoint内容的最佳功能!

javaScript ES2015对象继承经常询问问题 >在JavaScript中的经典和原型继承之间有什么区别?一个类定义一个对象的蓝图,对象是类的实例。继承是通过从超类创建子类来实现的。另一方面,JavaScript使用原型继承,其中对象直接从其他对象继承。这是更灵活的,因为可以在运行时扩展或动态更改对象。

>

>'超级'关键字在JavaScript ES2015中如何工作?在对象的父上调用功能。当在构造函数中使用时,“超级”关键字单独出现,必须在使用“此”关键字之前使用。 “超级”关键字也可用于在方法中的父对象上调用函数。>

> JavaScript中的“原型”是什么?在JavaScript中如何使用它在继承中?此属性是对另一个对象的原型对象的引用。创建函数时,其原型对象也会通过函数的原型属性创建并链接。当使用构造函数函数创建对象时,它从其构造函数的原型中继承了属性和方法。

> javaScript如何处理多个继承?

javaScript不直接支持多个继承。但是,可以使用混合蛋白间接实现它。混合蛋白是一种涉及将属性从一个对象复制到另一个对象的技术。这允许对象从多个来源继承属性和方法。

>

> javaScript ES2015中的'构造函数是什么?在javascript ES2015中如何使用它?用于创建和初始化类中的对象的特殊方法。在继承的上下文中,子类构造函数必须使用“超级”关键字调用超级类构造函数,然后才能使用'this'关键字。 >

JavaScript ES2015中的“扩展”关键字用于从超级类创建子类。子类继承了超类的所有属性和方法,但也可以添加新的属性或覆盖继承的属性。 >在JavaScript中,“类”是一种用作创建对象的蓝图的函数。它封装了在该数据上运行的数据和功能。另一方面,“原型”是一个对象,其他对象从中继承属性和方法。

>

>我如何在JavaScript ES2015中的子类中覆盖一个方法?您可以通过简单地定义子类中具有相同名称的方法来覆盖子类中的方法。新方法将在子类的实例上调用。 > JavaScript中的“新”关键字用于创建类或构造函数函数的实例。在继承的上下文中,“新”关键字用于创建一个子类的实例,该子类从超级类继承属性和方法。

如何在JavaScript中添加属性? >

>在JavaScript中,您可以通过简单地将值分配给原型对象上的属性来将属性添加到对象的原型中。然后,此属性将由从构造函数函数创建的所有对象继承。

>

以上是JavaScript ES2015中对象继承的模式的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆树的耳语 - 如何解锁抓钩
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1675
14
CakePHP 教程
1429
52
Laravel 教程
1333
25
PHP教程
1278
29
C# 教程
1257
24
Python vs. JavaScript:学习曲线和易用性 Python vs. JavaScript:学习曲线和易用性 Apr 16, 2025 am 12:12 AM

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

JavaScript和Web:核心功能和用例 JavaScript和Web:核心功能和用例 Apr 18, 2025 am 12:19 AM

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

JavaScript在行动中:现实世界中的示例和项目 JavaScript在行动中:现实世界中的示例和项目 Apr 19, 2025 am 12:13 AM

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。

了解JavaScript引擎:实施详细信息 了解JavaScript引擎:实施详细信息 Apr 17, 2025 am 12:05 AM

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python vs. JavaScript:社区,图书馆和资源 Python vs. JavaScript:社区,图书馆和资源 Apr 15, 2025 am 12:16 AM

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

Python vs. JavaScript:开发环境和工具 Python vs. JavaScript:开发环境和工具 Apr 26, 2025 am 12:09 AM

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

C/C在JavaScript口译员和编译器中的作用 C/C在JavaScript口译员和编译器中的作用 Apr 20, 2025 am 12:01 AM

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。 1)C 用于解析JavaScript源码并生成抽象语法树。 2)C 负责生成和执行字节码。 3)C 实现JIT编译器,在运行时优化和编译热点代码,显着提高JavaScript的执行效率。

Python vs. JavaScript:比较用例和应用程序 Python vs. JavaScript:比较用例和应用程序 Apr 21, 2025 am 12:01 AM

Python更适合数据科学和自动化,JavaScript更适合前端和全栈开发。1.Python在数据科学和机器学习中表现出色,使用NumPy、Pandas等库进行数据处理和建模。2.Python在自动化和脚本编写方面简洁高效。3.JavaScript在前端开发中不可或缺,用于构建动态网页和单页面应用。4.JavaScript通过Node.js在后端开发中发挥作用,支持全栈开发。

See all articles