广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >如何理解JavaScript的Mixin模式
  • 679
分享到

如何理解JavaScript的Mixin模式

2024-04-02 19:04:59 679人浏览 独家记忆
摘要

本篇文章为大家展示了如何理解javascript的Mixin模式,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。 在 JavaScript 中,我们只能继承

本篇文章为大家展示了如何理解javascript的Mixin模式,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

 在 JavaScript 中,我们只能继承单个对象。每个对象只能有一个 [[Prototype]]。并且每个类只可以扩展另外一个类。

但是有些时候这种设定(译注:单继承)会让人感到受限制。例如,我有一个 StreetSweeper类和一个 Bicycle 类,现在想要一个它们的  mixin:StreetSweepingBicycle 类。

或者,我们有一个 User 类和一个 EventEmitter 类来实现事件生成(event generation),并且我们想将  EventEmitter 的功能添加到 User 中,以便我们的用户可以触发事件(emit event)。

有一个概念可以帮助我们,叫做 “mixins”。

根据维基百科的定义,mixin 是一个包含可被其他类使用而无需继承的方法的类。

换句话说,mixin 提供了实现特定行为的方法,但是我们不单独使用它,而是使用它来将这些行为添加到其他类中。

一、一个 Mixin 实例

在 JavaScript 中构造一个 mixin  最简单的方式就是构造一个拥有实用方法的对象,以便我们可以轻松地将这些实用的方法合并到任何类的原型中。

例如,这个名为 sayHiMixin 的 mixin 用于给 User 添加一些“语言功能”:

// mixin let sayHiMixin = {   sayHi() {     alert(`Hello ${this.name}`);   },   sayBye() {     alert(`Bye ${this.name}`);   } };  // 用法: class User {   constructor(name) {     this.name = name;   } }  // 拷贝方法 Object.assign(User.prototype, sayHiMixin);  // 现在 User 可以打招呼了 new User("Dude").sayHi(); // Hello Dude!

这里没有继承,只有一个简单的方法拷贝。所以 User 可以从另一个类继承,还可以包括 mixin 来 "mix-in“ 其它方法,就像这样 :

class User extends Person {   // ... }  Object.assign(User.prototype, sayHiMixin);

Mixin 可以在自己内部使用继承。

例如,这里的 sayHiMixin 继承自 sayMixin:

let sayMixin = {   say(phrase) {     alert(phrase);   } };  let sayHiMixin = {   __proto__: sayMixin, // (或者,我们可以在这儿使用 Object.create 来设置原型)    sayHi() {     // 调用父类方法     super.say(`Hello ${this.name}`); // (*)   },   sayBye() {     super.say(`Bye ${this.name}`); // (*)   } };  class User {   constructor(name) {     this.name = name;   } }  // 拷贝方法 Object.assign(User.prototype, sayHiMixin);  // 现在 User 可以打招呼了 new User("Dude").sayHi(); // Hello Dude!

请注意,在 sayHiMixin 内部对父类方法 super.say() 的调用(在标有 (*) 的行)会在 mixin 的原型中查找方法,而不是在  class 中查找。

这是示意图(请参见图中右侧部分):

如何理解JavaScript的Mixin模式

这是因为方法 sayHi 和 sayBye 最初是在 sayHiMixin 中创建的。因此,即使复制了它们,但是它们的 [[HomeObject]]  内部属性仍引用的是 sayHiMixin,如上图所示。

当 super 在 [[HomeObject]].[[Prototype]] 中寻找父方法时,意味着它搜索的是  sayHiMixin.[[Prototype]],而不是 User.[[Prototype]]。

二、EventMixin

现在让我们为实际运用构造一个 mixin。

例如,许多浏览器对象的一个重要功能是它们可以生成事件。事件是向任何有需要的人“广播信息”的好方法。因此,让我们构造一个  mixin,使我们能够轻松地将与事件相关的函数添加到任意 class/object 中。

  • Mixin 将提供 .trigger(name, [...data]) 方法,以在发生重要的事情时“生成一个事件”。name  参数(arguments)是事件的名称,[...data] 是可选的带有事件数据的其他参数(arguments)。

  • 此外还有 .on(name, handler) 方法,它为具有给定名称的事件添加了 handler 函数作为监听器(listener)。当具有给定  name 的事件触发时将调用该方法,并从 .trigger 调用中获取参数(arguments)。

  • ……还有 .off(name, handler) 方法,它会删除 handler 监听器(listener)。

添加完 mixin 后,对象 user 将能够在访客登录时生成事件 "login"。另一个对象,例如 calendar  可能希望监听此类事件以便为登录的人加载日历。

或者,当一个菜单项被选中时,menu 可以生成 "select" 事件,其他对象可以分配处理程序以对该事件作出反应。诸如此类。

下面是代码:

  1. let eventMixin = { 

  2.    

  3.   on(eventName, handler) { 

  4.     if (!this._eventHandlers) this._eventHandlers = {}; 

  5.     if (!this._eventHandlers[eventName]) { 

  6.       this._eventHandlers[eventName] = []; 

  7.     } 

  8.     this._eventHandlers[eventName].push(handler); 

  9.   }, 

  10.  

  11.    

  12.   off(eventName, handler) { 

  13.     let handlers = this._eventHandlers?.[eventName]; 

  14.     if (!handlers) return; 

  15.     for (let i = 0; i < handlers.length; i++) { 

  16.       if (handlers[i] === handler) { 

  17.         handlers.splice(i--, 1); 

  18.       } 

  19.     } 

  20.   }, 

  21.  

  22.    

  23.   trigger(eventName, ...args) { 

  24.     if (!this._eventHandlers?.[eventName]) { 

  25.       return; // 该事件名称没有对应的事件处理程序(handler) 

  26.     } 

  27.  

  28.     // 调用事件处理程序(handler) 

  29.     this._eventHandlers[eventName].forEach(handler => handler.apply(this, args)); 

  30.   } 

  31. }; 


  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. .on(eventName, handler) &mdash; 指定函数 handler  以在具有对应名称的事件发生时运行。从技术上讲,这儿有一个用于存储每个事件名称对应的处理程序(handler)的 _eventHandlers  属性,在这儿该属性就会将刚刚指定的这个 handler 添加到列表中。

  3. .off(eventName, handler) &mdash; 从处理程序列表中删除指定的函数。

  4. .trigger(eventName, ...args) &mdash; 生成事件:所有 _eventHandlers[eventName]  中的事件处理程序(handler)都被调用,并且 ...args 会被作为参数传递给它们。

用法:

// 创建一个 class class Menu {   choose(value) {     this.trigger("select", value);   } } // 添加带有事件相关方法的 mixin Object.assign(Menu.prototype, eventMixin);  let menu = new Menu();  // 添加一个事件处理程序(handler),在被选择时被调用: menu.on("select", value => alert(`Value selected: ${value}`));  // 触发事件 => 运行上述的事件处理程序(handler)并显示: // 被选中的值:123 menu.choose("123");

现在,如果我们希望任何代码对菜单选择作出反应,我们可以使用 menu.on(...) 进行监听。

使用 eventMixin 可以轻松地将此类行为添加到我们想要的多个类中,并且不会影响继承链。

三、总结

Mixin &mdash; 是一个通用的面向对象编程术语:一个包含其他类的方法的类。

一些其它编程语言允许多重继承。JavaScript 不支持多重继承,但是可以通过将方法拷贝到原型中来实现 mixin。

我们可以使用 mixin 作为一种通过添加多种行为来扩充类的方法。

如果 Mixins 意外覆盖了现有类的方法,那么它们可能会成为一个冲突点。因此,通常应该仔细考虑 mixin  的命名方法,以最大程度地降低发生这种冲突的可能性。

上述内容就是如何理解JavaScript的Mixin模式,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网JavaScript频道。

--结束END--

本文标题: 如何理解JavaScript的Mixin模式

本文链接: https://www.lsjlt.com/news/82263.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何理解JavaScript的Mixin模式
    本篇文章为大家展示了如何理解JavaScript的Mixin模式,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。 在 JavaScript 中,我们只能继承...
    99+
    2022-10-19
  • 如何理解JavaScript的设计模式
    本篇文章为大家展示了如何理解JavaScript的设计模式,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。  今天我们就聊一下这三个设计模式  单例模式 / 组合模...
    99+
    2022-10-19
  • javascript中如何理解设计模式
    本篇内容介绍了“javascript中如何理解设计模式”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2022-10-19
  • JavaScript 设计模式中的代理模式详解
    前言: 代理模式,代理(proxy)是一个对象,它可以用来控制对另一个对象的访问。 现在页面上有一个香港回归最想听的金典曲目列表: <ul id="container">...
    99+
    2022-11-13
  • 理解JavaScript设计模式中的单例模式
    单例模式(Singleton Pattern)是最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 单例模式涉及到一个单一的类,该类负责创建自己...
    99+
    2022-11-13
  • 理解JavaScript设计模式中的建造者模式
    我们在前面已经提过设计模式创建型模式的 3 种工厂模式 和 单例模式;本篇带来同属创建型模式的“建造者模式” 建造者模式(Builder Pattern)使...
    99+
    2022-11-13
  • 如何理解Java设计模式的解释器模式
    本篇内容主要讲解“如何理解Java设计模式的解释器模式”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解Java设计模式的解释器模式”吧!一、什么是解释器模式定义:给定一个语言,定义一个文法...
    99+
    2023-06-25
  • 一文理解JavaScript中的单例模式
    JS 单例模式是一种常用的设计模式,它可以保证一个类只有一个实例。这种模式主要用于管理全局变量,避免命名冲突和重复加载,同时也可以减少内存占用,提高代码的可维护性和可扩展性。价值场景JS 单例模式通常适用于以下场景:管理全局变量使用单例模式...
    99+
    2023-05-14
    单例模式 前端 JavaScript 面试
  • 如何理解Java设计模式的命令模式
    本篇内容主要讲解“如何理解Java设计模式的命令模式”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解Java设计模式的命令模式”吧!一、什么是命令模式命令模式是一个高内聚的模式,其定义为:...
    99+
    2023-06-25
  • 如何理解Java设计模式的状态模式
    本篇内容介绍了“如何理解Java设计模式的状态模式”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、什么是状态模式定义:当一个对象的内在状态...
    99+
    2023-06-25
  • 如何理解Java设计模式的享元模式
    本篇内容介绍了“如何理解Java设计模式的享元模式”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、引言大家都知道单例模式,通过一个全局变量...
    99+
    2023-06-25
  • 如何理解Java设计模式的组合模式
    这篇文章主要介绍“如何理解Java设计模式的组合模式”,在日常操作中,相信很多人在如何理解Java设计模式的组合模式问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何理解Java设计模式的组合模式”的疑惑有所...
    99+
    2023-06-25
  • 如何理解Java设计模式的桥接模式
    这篇文章主要讲解了“如何理解Java设计模式的桥接模式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解Java设计模式的桥接模式”吧!一、什么是桥接模式桥接模式(Bridge Patt...
    99+
    2023-06-25
  • 如何理解Java设计模式的装饰模式
    这篇文章主要介绍“如何理解Java设计模式的装饰模式”,在日常操作中,相信很多人在如何理解Java设计模式的装饰模式问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何理解Java设计模式的装饰模式”的疑惑有所...
    99+
    2023-06-25
  • 如何理解Java设计模式的单例模式
    这篇文章主要讲解了“如何理解Java设计模式的单例模式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解Java设计模式的单例模式”吧!一、什么是单例模式单例模式是一种常用的软件设计模式...
    99+
    2023-06-25
  • 如何理解JavaScript模块化
    目录1. 浏览器支持2. export 导出模块3. import 导入模块4. 创建模块对象5. export import 中转站6. 动态加载模块1. 浏览器支持 使用Java...
    99+
    2022-11-12
  • JavaScript 模块化如何理解
    这期内容当中小编将会给大家带来有关JavaScript 模块化如何理解,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。前言:1.概念将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并...
    99+
    2023-06-22
  • 如何理解设计模式之桥模式
    本篇内容介绍了“如何理解设计模式之桥模式”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!举个例子桥模式的主要...
    99+
    2022-10-19
  • 如何理解JavaScript中的ES模块
    如何理解JavaScript中的ES模块,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。模块在每个编程语言中都能找到。它是一种能在一个代码块...
    99+
    2022-10-19
  • 一文理解JavaScript装饰器模式
    装饰器模式想必大家并不陌生:它允许向一个现有的对象添加新的功能,同时又不改变其结构,属于结构型模式,它是作为现有的类的一个包装。 这种模式创建了一个装饰类,用来包装原有的类,并在保持...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作