CINXE.COM

<!DOCTYPE html><html lang="fr" data-theme-enabled="1"><head><script>window.currentUser = null;</script><script>window.shopCurrency = "EUR";</script><script>window.localCurrency = "EUR";</script><script>window.countryCode = "sg";</script><script>window.rateShopTo = {"EUR":1,"USD":1.137241121274256,"AMD":443.83469404233495};</script><title itemprop="name">Les mixins</title><link href="/pack/styles.100020a0bc7cf13be729.css" rel="stylesheet"><meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes, minimum-scale=1.0"><meta name="apple-mobile-web-app-capable" content="yes"><!-- chrome autotranslate is enabled only for "en" main version--><meta name="google" content="notranslate"><script>if (window.devicePixelRatio > 1) document.cookie = 'pixelRatio=' + window.devicePixelRatio + ';path=/;expires=Tue, 19 Jan 2038 03:14:07 GMT';</script><link href="//fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic" rel="stylesheet"><link rel="apple-touch-icon-precomposed" href="/img/favicon/apple-touch-icon-precomposed.png"><link rel="canonical" href="https://fr.javascript.info/mixins"><meta name="msapplication-TileColor" content="#222A2C"><meta name="msapplication-TileImage" content="/img/favicon/tileicon.png"><link rel="icon" href="/img/favicon/favicon.png"><meta itemprop="image" content="https://fr.javascript.info/img/site_preview_en_512x512.png"><meta property="og:title" content="Les mixins"><meta property="og:image" content="https://fr.javascript.info/img/site_preview_en_1200x630.png"><meta property="og:image:type" content="image/png"><meta property="og:image:width" content="1200"><meta property="og:image:height" content="630"><meta property="fb:admins" content="100001562528165"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="Les mixins"><meta name="twitter:site" content="@iliakan"><meta name="twitter:creator" content="@iliakan"><meta name="twitter:image" content="https://fr.javascript.info/img/site_preview_en_512x512.png"><meta name="google-adsense-account" content="ca-pub-6204518652652613"><link rel="prev" href="/instanceof"><link rel="next" href="/error-handling"><script data-collect-dnt="true" async src="https://scripts.simpleanalyticscdn.com/latest.js"></script><script>window.GA_ID = "UA-2056213-15";</script><script>window.YANDEX_METRIKA_ID = 32184394;</script><script>{function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","G-2LWB61WGYJ")}</script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-2LWB61WGYJ"></script><script>window.metrika={reachGoal:function(){}},window.yandex_metrika_callbacks=[function(){try{window.metrika=new Ya.Metrika({id:YANDEX_METRIKA_ID,webvisor:!0,clickmap:!0,params:{user:window.currentUser&&window.currentUser.id}}),metrika.trackLinks({delay:150}),window.addEventListener("error",function(r){window.metrika.reachGoal("JSERROR",{src:(r.filename||r.errorUrl)+": "+(r.lineno||r.errorLine),stack:r.stack||r.error&&r.error.stack,message:r.message})})}catch(r){}}];</script><script src="//mc.yandex.ru/metrika/watch.js" async></script><script>window.RECAPTCHA_ID = "6LfmLAEVAAAAAJMykMnf7aY8nkyTRmYi2ynx51R1";</script><script src="/pack/init.5ce4add6d34ce3873b87.js"></script><script src="/pack/head.bda20409a4233b435003.js" defer></script><script> let eventMixin = { /** * Souscrire à l'événement, usage: * menu.on('select', function(item) { ... } */ on(eventName, handler) { if (!this._eventHandlers) this._eventHandlers = {}; if (!this._eventHandlers[eventName]) { this._eventHandlers[eventName] = []; } this._eventHandlers[eventName].push(handler); }, /** * Annuler la souscription, usage: * menu.off('select', handler) */ off(eventName, handler) { let handlers = this._eventHandlers?.[eventName]; if (!handlers) return; for(let i = 0; i < handlers.length; i++) { if (handlers[i] == handler) { handlers.splice(i--, 1); } } }, /** * Générer un événement avec le nom et les données donnés * this.trigger('select', data1, data2); */ trigger(eventName, ...args) { if (!this._eventHandlers || !this._eventHandlers[eventName]) { return; // aucun gestionnaire pour ce nom d'événement } // appeler les gestionnaires this._eventHandlers[eventName].forEach(handler => handler.apply(this, args)); } }; </script> <meta property="og:title" content="Les mixins"><meta property="og:type" content="article"><script src="/pack/tutorial.6dc548047f76247d0296.js" defer></script><script src="/pack/footer.8204c68365693e9309b7.js" defer></script></head><body class="no-icons"><script>window.fontTest();</script><div class="page-wrapper page-wrapper_sidebar_on"><!--[if IE]><div style="color:red;text-align:center">Désolé, Internet Explorer n'est pas pris en charge, veuillez utiliser un navigateur plus récent.</div><![endif]--><div class="sitetoolbar sitetoolbar_tutorial"><script>window.langs = [{"code":"ar","name":"Arabic"},{"code":"az","name":"Azerbaijani"},{"code":"bg","name":"Bulgarian"},{"code":"bn","name":"Bengali"},{"code":"bs","name":"Bosnian"},{"code":"ca","name":"Catalan"},{"code":"cs","name":"Czech"},{"code":"da","name":"Danish"},{"code":"de","name":"German"},{"code":"el","name":"Greek"},{"code":"en","name":"English"},{"code":"es","name":"Spanish"},{"code":"fa","name":"Persian (Farsi)"},{"code":"fi","name":"Finnish"},{"code":"fr","name":"French"},{"code":"he","name":"Hebrew"},{"code":"hi","name":"Hindi"},{"code":"hr","name":"Croatian"},{"code":"hu","name":"Hungarian"},{"code":"hy","name":"Armenian"},{"code":"id","name":"Indonesian"},{"code":"it","name":"Italian"},{"code":"ja","name":"Japanese"},{"code":"ka","name":"Georgian"},{"code":"kk","name":"Kazakh"},{"code":"km","name":"Central Khmer"},{"code":"ko","name":"Korean"},{"code":"ku","name":"Kurdish"},{"code":"ky","name":"Kyrgyz"},{"code":"lt","name":"Lithuanian"},{"code":"me","name":"Montenegrin"},{"code":"ml","name":"Malayalam"},{"code":"ms","name":"Malay"},{"code":"my","name":"Burmese"},{"code":"nl","name":"Dutch"},{"code":"no","name":"Norvegian"},{"code":"pa","name":"Punjabi"},{"code":"pl","name":"Polish"},{"code":"pt","name":"Portuguese"},{"code":"ro","name":"Romanian"},{"code":"ru","name":"Russian"},{"code":"si","name":"Sinhala"},{"code":"sk","name":"Slovak"},{"code":"sl","name":"Slovenian"},{"code":"sq","name":"Albanian"},{"code":"sr","name":"Serbian"},{"code":"ta","name":"Tamil"},{"code":"te","name":"Telugu"},{"code":"test","name":"Test"},{"code":"th","name":"Thai"},{"code":"tk","name":"Turkmen"},{"code":"tr","name":"Turkish"},{"code":"ug","name":"Uyghur"},{"code":"uk","name":"Ukrainian"},{"code":"ur","name":"Urdu"},{"code":"uz","name":"Uzbek"},{"code":"v2","name":"v2"},{"code":"vi","name":"Vietnamese"},{"code":"zh-hant","name":"Chinese Traditional"},{"code":"zh","name":"Chinese"}];</script><script>window.lang = "fr";</script><div class="sitetoolbar__content"><div class="sitetoolbar__lang-switcher"><button class="sitetoolbar__dropdown-button" data-dropdown-toggler>FR</button><div class="sitetoolbar__dropdown-wrap"><div class="sitetoolbar__dropdown-body"><div class="sitetoolbar__lang-switcher-body"><div class="supported-langs supported-langs_toolbar"><div class="supported-langs__container"><ul class="supported-langs__list" style="height:200px"><li class="supported-langs__item"><a class="supported-langs__link" href="https://ar.javascript.info/mixins"><span class="supported-langs__brief">AR</span><span class="supported-langs__title">عربي</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://javascript.info/mixins"><span class="supported-langs__brief">EN</span><span class="supported-langs__title">English</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://es.javascript.info/mixins"><span class="supported-langs__brief">ES</span><span class="supported-langs__title">Español</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://fa.javascript.info/mixins"><span class="supported-langs__brief">FA</span><span class="supported-langs__title">فارسی</span></a></li><li class="supported-langs__item supported-langs__item_current"><a class="supported-langs__link" href="https://fr.javascript.info/mixins"><span class="supported-langs__brief">FR</span><span class="supported-langs__title">Français</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://id.javascript.info/mixins"><span class="supported-langs__brief">ID</span><span class="supported-langs__title">Indonesia</span></a></li></ul><ul class="supported-langs__list" style="height:200px"><li class="supported-langs__item"><a class="supported-langs__link" href="https://it.javascript.info/mixins"><span class="supported-langs__brief">IT</span><span class="supported-langs__title">Italiano</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://ja.javascript.info/mixins"><span class="supported-langs__brief">JA</span><span class="supported-langs__title">日本語</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://ko.javascript.info/mixins"><span class="supported-langs__brief">KO</span><span class="supported-langs__title">한국어</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://learn.javascript.ru/mixins"><span class="supported-langs__brief">RU</span><span class="supported-langs__title">Русский</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://tr.javascript.info/mixins"><span class="supported-langs__brief">TR</span><span class="supported-langs__title">Türkçe</span></a></li><li class="supported-langs__item"><a class="supported-langs__link" href="https://uk.javascript.info/mixins"><span class="supported-langs__brief">UK</span><span class="supported-langs__title">Українська</span></a></li></ul><ul class="supported-langs__list" style="height:20px"><li class="supported-langs__item"><a class="supported-langs__link" href="https://zh.javascript.info/mixins"><span class="supported-langs__brief">ZH</span><span class="supported-langs__title">简体中文</span></a></li></ul></div><div class="supported-langs__text"><p>Nous souhaitons rendre ce projet open source disponible pour les gens du monde entier.</p> <p><a href="https://javascript.info/translate">Aidez-nous à traduire</a> le contenu de ce tutoriel dans votre langue!</p> </div></div></div></div></div></div><div class="sitetoolbar__logo-wrap"><a class="sitetoolbar__link sitetoolbar__link_logo" href="/"><img class="sitetoolbar__logo sitetoolbar__logo_normal" src="/img/sitetoolbar__logo_en.svg" width="200" alt="" role="presentation"/><img class="sitetoolbar__logo sitetoolbar__logo_normal sitetoolbar__logo_dark" src="/img/sitetoolbar__logo_en-white.svg" width="200" alt="" role="presentation"/><img class="sitetoolbar__logo sitetoolbar__logo_small" src="/img/sitetoolbar__logo_small_en.svg" width="70" alt="" role="presentation"/><img class="sitetoolbar__logo sitetoolbar__logo_small sitetoolbar__logo_dark" src="/img/sitetoolbar__logo_small_en-white.svg" width="70" alt="" role="presentation"/><script>Array.prototype.forEach.call(document.querySelectorAll("img.sitetoolbar__logo"),function(e){let t=document.createElement("object");t.type="image/svg+xml",t.className=e.className,t.style.cssText="left:0;top:0;position:absolute",t.onload=function(){t.onload=null,e.style.visibility="hidden"},t.data=e.src,e.parentNode.insertBefore(t,e)});</script></a></div><div class="sitetoolbar__nav-toggle-wrap"><button class="sitetoolbar__nav-toggle" type="button"></button></div><nav class="sitetoolbar__sections"><ul class="sitetoolbar__sections-list"></ul></nav><div class="sitetoolbar__right-button-wrap"><a class="sitetoolbar-right-button sitetoolbar-right-button_courses" href="/ebook"><span class="sitetoolbar-right-button__extra-text">Acheter</span>EPUB/PDF</a></div><div class="sitetoolbar__theme-switcher"><div class="theme-changer"><label class="theme-changer__label" for="theme-changer-input" data-tooltip="Change theme"><input class="theme-changer__input" type="checkbox" id="theme-changer-input" data-theme-changer="data-theme-changer"/><span class="theme-changer__icon theme-changer__icon_light-theme"></span><span class="theme-changer__icon theme-changer__icon_dark-theme"></span></label></div></div><div class="sitetoolbar__search-wrap"><div class="sitetoolbar__search-content"><button class="sitetoolbar__search-toggle" type="button"></button><form class="sitetoolbar__search" method="GET" action="/search"><div class="sitetoolbar__search-input"><div class="text-input"><input class="text-input__control" name="query" placeholder="Rechercher sur Javascript.info" required="required" type="text"/></div><button class="sitetoolbar__find" type="submit">Recherche</button></div></form></div></div></div><div class="tablet-menu"><div class="tablet-menu__line"><div class="tablet-menu__content"><form class="tablet-menu-search" action="/search/"><input class="tablet-menu-search__input" type="search" name="query" placeholder="Rechercher dans le tutoriel" required="required"/><button class="tablet-menu-search__button" type="submit" name="type" value="articles">Recherche</button></form></div></div><div class="tablet-menu__line"><div class="tablet-menu__content"><a class="map" href="/tutorial/map" data-action="tutorial-map"><span class="map__text">Carte du tutoriel</span></a></div></div><div class="tablet-menu__line"><div class="tablet-menu__content"><div class="theme-changer theme-changer_tablet-menu theme-changer_has-label"><label class="theme-changer__label" for="theme-changer-input-tablet" data-tooltip="Change theme"><input class="theme-changer__input" type="checkbox" id="theme-changer-input-tablet" data-theme-changer="data-theme-changer"/><span class="theme-changer__icon theme-changer__icon_light-theme"></span><span class="theme-changer__icon theme-changer__icon_dark-theme"></span><span class="theme-changer__label-text theme-changer__label-text_light-theme">Light theme</span><span class="theme-changer__label-text theme-changer__label-text_dark-theme">Dark theme</span></label></div></div></div><div class="tablet-menu__line"><div class="tablet-menu__content"><div class="share-icons"><span class="share-icons__title">Partager</span><a class="share share_tw" href="https://twitter.com/share?url=https%3A%2F%2Ffr.javascript.info%2Fmixins" rel="nofollow"></a><a class="share share_fb" href="https://www.facebook.com/sharer/sharer.php?s=100&amp;p%5Burl%5D=https%3A%2F%2Ffr.javascript.info%2Fmixins" rel="nofollow"></a></div></div></div><div class="tablet-menu__line"><div class="tablet-menu__content"><select class="tablet-menu__nav input-select input-select input-select_small" onchange="if(this.value) window.location.href=this.value"><option value="https://ar.javascript.info/mixins">عربي</option><option value="https://javascript.info/mixins">English</option><option value="https://es.javascript.info/mixins">Español</option><option value="https://fa.javascript.info/mixins">فارسی</option><option value="https://fr.javascript.info/mixins" selected>Français</option><option value="https://id.javascript.info/mixins">Indonesia</option><option value="https://it.javascript.info/mixins">Italiano</option><option value="https://ja.javascript.info/mixins">日本語</option><option value="https://ko.javascript.info/mixins">한국어</option><option value="https://learn.javascript.ru/mixins">Русский</option><option value="https://tr.javascript.info/mixins">Türkçe</option><option value="https://uk.javascript.info/mixins">Українська</option><option value="https://zh.javascript.info/mixins">简体中文</option></select></div></div></div><progress class="tutorial-progress" data-sticky value="72" max="93" data-tooltip="Cours 72 de 93"></progress></div><div class="page page_sidebar_on page_inner_padding"><script>if(localStorage.noSidebar){document.querySelector(".page").classList.remove("page_sidebar_on");let e=document.querySelector(".page-wrapper");e&&e.classList.remove("page-wrapper_sidebar_on")}setTimeout(function(){document.querySelector(".page").classList.add("page_sidebar-animation-on")});</script><div class="page__inner"><main class="main main_width-limit"><header class="main__header"><div class="main__header-inner"><div class="main__header-group"><ol class="breadcrumbs"><li class="breadcrumbs__item breadcrumbs__item_home"><a class="breadcrumbs__link" href="/"><span class="breadcrumbs__hidden-text">Tutoriel</span></a></li><li class="breadcrumbs__item" id="breadcrumb-1"><a class="breadcrumbs__link" href="/js"><span>JavaScript le langage</span></a></li><li class="breadcrumbs__item" id="breadcrumb-2"><a class="breadcrumbs__link" href="/classes"><span>Classes</span></a></li><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Tutoriel","item":"https://fr.javascript.info/"},{"@type":"ListItem","position":2,"name":"JavaScript le langage","item":"https://fr.javascript.info/js"},{"@type":"ListItem","position":3,"name":"Classes","item":"https://fr.javascript.info/classes"}]}</script></ol><div class="updated-at" data-tooltip="Dernière mise à jour le 29 juin 2023"><div class="updated-at__content">29 juin 2023</div></div></div><h1 class="main__header-title">Les mixins</h1></div></header><div class="content"><article class="formatted" itemscope itemtype="http://schema.org/TechArticle"><meta itemprop="name" content="Les mixins"><div itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="email" content="iliakan@gmail.com"><meta itemprop="name" content="Ilya Kantor"></div><div itemprop="articleBody"><p>En JavaScript, nous ne pouvons hériter que d’un seul objet. Il ne peut y avoir qu’un <code>[[Prototype]]</code> pour un objet. Et une classe peut étendre qu’une seule autre classe.</p> <p>Mais parfois, cela semble limitant. Par exemple, nous avons une classe <code>StreetSweeper</code> et une classe <code>Bicycle</code>, et nous voulons faire leur mélange : un <code>StreetSweepingBicycle</code>.</p> <p>Ou nous avons une classe <code>User</code> et une classe <code>EventEmitter</code> qui implémente la génération d’événements, et nous aimerions ajouter la fonctionnalité de <code>EventEmitter</code> à <code>User</code> afin que nos utilisateurs puissent émettre des événements.</p> <p>Il existe un concept qui peut aider ici, appelé “mixins”.</p> <p>Comme défini dans Wikipedia, un <a href="https://fr.wikipedia.org/wiki/Mixin">mixin</a> est une classe contenant des méthodes qui peuvent être utilisées par d’autres classes sans avoir à en hériter.</p> <p>En d’autres termes, un <em>mixin</em> fournit des méthodes qui implémentent un certain comportement, mais nous ne l’utilisons pas seul, nous l’utilisons pour ajouter le comportement à d’autres classes.</p> <h2><a class="main__anchor" name="un-exemple-de-mixin" href="#un-exemple-de-mixin">Un exemple de mixin</a></h2><p>Le moyen le plus simple d’implémenter un mixin en JavaScript est de créer un objet avec des méthodes utiles, de sorte que nous puissions facilement les fusionner dans un prototype de n’importe quelle classe.</p> <p>Par exemple ici, le mixin <code>sayHiMixin</code> est utilisé pour ajouter un peu de “discours” à <code>User</code> :</p> <div id="whj4ck2vm6" data-trusted="1" class="code-example" data-highlight="[{&quot;start&quot;:10,&quot;end&quot;:10},{&quot;start&quot;:0,&quot;end&quot;:0}]"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="exécuter" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="ouvrir dans une sandbox" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>// mixin let sayHiMixin = { sayHi() { alert(`Hello ${this.name}`); }, sayBye() { alert(`Bye ${this.name}`); } }; // usage: class User { constructor(name) { this.name = name; } } // copier les méthodes Object.assign(User.prototype, sayHiMixin); // maintenant User peut dire bonjour new User(&quot;Dude&quot;).sayHi(); // Hello Dude!</code></pre> </div> </div> </div><p>Il n’y a pas d’héritage, mais une simple copie de méthode. Ainsi, <code>User</code> peut hériter d’une autre classe et inclure le mixin pour ajouter les méthodes supplémentaires, comme ceci :</p> <div id="vfxxmqw0gd" data-trusted="1" class="code-example"> <div class="codebox code-example__codebox"> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>class User extends Person { // ... } Object.assign(User.prototype, sayHiMixin);</code></pre> </div> </div> </div><p>Les mixins peuvent utiliser l’héritage à l’intérieur d’eux-mêmes.</p> <p>Par exemple, ici <code>sayHiMixin</code> hérite de <code>sayMixin</code> :</p> <div id="vy43xcbcce" data-trusted="1" class="code-example" data-highlight="[{&quot;start&quot;:10,&quot;end&quot;:10}]"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="exécuter" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="ouvrir dans une sandbox" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let sayMixin = { say(phrase) { alert(phrase); } }; let sayHiMixin = { __proto__: sayMixin, // (ou nous pourrions utiliser Object.setPrototypeOf pour définir le prototype ici) sayHi() { // appeler la méthode du parent super.say(`Hello ${this.name}`); // (*) }, sayBye() { super.say(`Bye ${this.name}`); // (*) } }; class User { constructor(name) { this.name = name; } } // copier les méthodes Object.assign(User.prototype, sayHiMixin); // maintenant User peut dire bonjour new User(&quot;Dude&quot;).sayHi(); // Hello Dude!</code></pre> </div> </div> </div><p>Veuillez noter que l’appel à la méthode du parent <code>super.say()</code> à partir de <code>sayHiMixin</code> (aux lignes étiquetées avec <code>(*)</code>) recherche la méthode dans le prototype de ce mixin, pas la classe.</p> <p>Voici le schéma (voir la partie droite) :</p> <figure><div class="image" style="width:486px"> <div class="image__ratio" style="padding-top:60.69958847736625%"></div> <object type="image/svg+xml" data="/article/mixins/mixin-inheritance.svg" width="486" height="295" class="image__image" data-use-theme> <img src="/article/mixins/mixin-inheritance.svg" alt="" width="486" height="295"> </object> </div></figure><p>C’est parce que les méthodes <code>sayHi</code> et <code>sayBye</code> ont été initialement créées dans <code>sayHiMixin</code>. Ainsi, même si elles ont été copiées, leur propriété interne <code>[[HomeObject]]</code> fait référence à <code>sayHiMixin</code>, comme indiqué sur l’image ci-dessus.</p> <p>Comme <code>super</code> cherche des méthodes du parent dans <code>[[HomeObject]].[[Prototype]]</code>, cela signifie qu’il cherche <code>sayHiMixin.[[Prototype]]</code>.</p> <h2><a class="main__anchor" name="eventmixin" href="#eventmixin">EventMixin</a></h2><p>Faisons maintenant un mixin concret.</p> <p>Une caractéristique importante de nombreux objets de navigateur (par exemple) est qu’ils peuvent générer des événements. Les événements sont un excellent moyen de “diffuser des informations” à tous ceux qui le souhaitent. Faisons donc un mixin qui permet d’ajouter facilement des fonctions relatives aux événements à n’importe quelle classe/objet.</p> <ul> <li>Le mixin fournira une méthode <code>.trigger(name, [... data])</code> pour “générer un événement” quand quelque chose d’important lui arrive. L’argument <code>name</code> est un nom de l’événement, éventuellement suivi d’arguments supplémentaires avec les données d’événement.</li> <li>Également la méthode <code>.on(name, handler)</code> qui ajoute la fonction <code>handler</code> en tant qu’écouteur aux événements portant le nom donné. Il sera appelé lorsqu’un événement avec le <code>name</code> donné se déclenche, et récupérera les arguments de l’appel <code>.trigger</code>.</li> <li>… Et la méthode <code>.off(name, handler)</code> qui supprime le programme d’écoute <code>handler</code>.</li> </ul> <p>Après avoir ajouté le mixin, un objet <code>user</code> sera capable de générer un événement <code>&quot;login&quot;</code> lorsque le visiteur se connectera. Un autre objet, par exemple, <code>calendar</code> peut vouloir écouter de tels événements pour charger le calendrier de la personne connectée.</p> <p>Ou bien, un <code>menu</code> peut générer l’événement <code>&quot;select&quot;</code> lorsqu’un élément de menu est sélectionné, et d’autres objets peuvent affecter des gestionnaires pour réagir à cet événement. Etc.</p> <p>Voici le code :</p> <div id="886vr7nh6t" data-trusted="1" class="code-example"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="exécuter" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="ouvrir dans une sandbox" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>let eventMixin = { /** * Souscrire à l'événement, usage : * menu.on('select', function(item) { ... } */ on(eventName, handler) { if (!this._eventHandlers) this._eventHandlers = {}; if (!this._eventHandlers[eventName]) { this._eventHandlers[eventName] = []; } this._eventHandlers[eventName].push(handler); }, /** * Annuler la souscription, usage : * menu.off('select', handler) */ off(eventName, handler) { let handlers = this._eventHandlers?.[eventName]; if (!handlers) return; for (let i = 0; i &lt; handlers.length; i++) { if (handlers[i] === handler) { handlers.splice(i--, 1); } } }, /** * Générer un événement avec le nom et les données donnés * this.trigger('select', data1, data2); */ trigger(eventName, ...args) { if (!this._eventHandlers?.[eventName]) { return; // aucun gestionnaire pour ce nom d'événement } // appeler les gestionnaires this._eventHandlers[eventName].forEach(handler =&gt; handler.apply(this, args)); } };</code></pre> </div> </div> </div><ul> <li><code>.on(eventName, handler)</code> – assigne la fonction <code>handler</code> à exécuter lorsque l’événement portant ce nom se produit. Techniquement, il existe une propriété <code>_eventHandlers</code>, qui stocke un tableau de gestionnaires pour chaque nom d’événement, et il l’ajoute simplement à la liste.</li> <li><code>.off(eventName, handler)</code> – supprime la fonction de la liste des gestionnaires.</li> <li><code>.trigger(eventName, ... args)</code> – génère l’événement : tous les gestionnaires de <code>_eventHandlers[eventName]</code> sont appelés, avec une liste d’arguments <code>...args</code>.</li> </ul> <p>Usage :</p> <div id="fjdum1co8j" data-trusted="1" class="code-example" data-highlight="[{&quot;start&quot;:12,&quot;end&quot;:12}]"> <div class="codebox code-example__codebox"> <div class="toolbar codebox__toolbar"> <div class="toolbar__tool"> <a href="#" title="exécuter" data-action="run" class="toolbar__button toolbar__button_run"></a> </div> <div class="toolbar__tool"> <a href="#" title="ouvrir dans une sandbox" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a> </div> </div> <div class="codebox__code" data-code="1"> <pre class="line-numbers language-javascript"><code>// Créez une classe class Menu { choose(value) { this.trigger(&quot;select&quot;, value); } } // Ajouter le mixin avec les méthodes liées aux événements Object.assign(Menu.prototype, eventMixin); let menu = new Menu(); // ajouter un gestionnaire, à appeler lors de la sélection : menu.on(&quot;select&quot;, value =&gt; alert(`Value selected: ${value}`)); // déclenche l'événement =&gt; le gestionnaire ci-dessus s'exécute et affiche : // Value selected: 123 menu.choose(&quot;123&quot;);</code></pre> </div> </div> </div><p>Maintenant, si nous souhaitons que le code réagisse lors de la sélection du menu, nous pouvons l’écouter avec <code>menu.on(...)</code>.</p> <p>Et le mixin <code>eventMixin</code> facilite l’ajout d’un tel comportement à autant de classes que nous le voudrions, sans interférer avec la chaîne d’héritage.</p> <h2><a class="main__anchor" name="resume" href="#resume">Résumé</a></h2><p><em>Mixin</em> est un terme générique de programmation orienté objet : une classe contenant des méthodes pour d’autres classes.</p> <p>D’autres langages autorisent l’héritage multiple. JavaScript ne prend pas en charge l’héritage multiple, mais les mixins peuvent être implémentés en copiant les méthodes dans le prototype.</p> <p>Nous pouvons utiliser les mixins comme moyen d’ajouter à une classe plusieurs comportements, comme la gestion d’événements, comme nous l’avons vu ci-dessus.</p> <p>Les mixins peuvent devenir un point de conflit s’ils écrasent accidentellement les méthodes de classe existantes. En règle générale, il convient de bien réfléchir aux méthodes de nommage d’un mixin, afin de minimiser la probabilité que cela se produise.</p> </div></article></div><div class="page__nav-wrap"><a class="page__nav page__nav_prev" href="/instanceof" data-tooltip="Vérification de classe : &quot;instanceof&quot;"><span class="page__nav-text"><span class="page__nav-text-shortcut"></span></span><span class="page__nav-text-alternate">Cours précédent</span></a><a class="page__nav page__nav_next" href="/error-handling" data-tooltip="La gestion des erreurs"><span class="page__nav-text"><span class="page__nav-text-shortcut"></span></span><span class="page__nav-text-alternate">Prochain cours</span></a></div><div class="article-tablet-foot tablet-only"><div class="article-tablet-foot__layout"><div class="share-icons"><span class="share-icons__title">Partager</span><a class="share share_tw" href="https://twitter.com/share?url=https%3A%2F%2Ffr.javascript.info%2Fmixins" rel="nofollow"></a><a class="share share_fb" href="https://www.facebook.com/sharer/sharer.php?s=100&amp;p%5Burl%5D=https%3A%2F%2Ffr.javascript.info%2Fmixins" rel="nofollow"></a></div><div class="article-tablet-foot__map"><a class="map" href="/tutorial/map" data-action="tutorial-map"><span class="map__text">Carte du tutoriel</span></a></div></div></div><div class="comments formatted" id="comments"><div class="comments__header"><h2 class="comments__header-title"><a href="#comments" name="comments">Commentaires</a></h2><div class="comments__read-before"><span class="comments__read-before-link">lire ceci avant de commenter…</span><div class="comments__read-before-popup"><div class="comments__read-before-popup-i"><ul><li>Si vous avez des améliorations à suggérer, merci de <a href="https://github.com/javascript-tutorial/en.javascript.info/issues/new">soumettre une issue GitHub</a> ou une pull request au lieu de commenter.</li><li>Si vous ne comprenez pas quelque chose dans l'article, merci de préciser.</li><li>Pour insérer quelques bouts de code, utilisez la balise <code>&lt;code&gt;</code>, pour plusieurs lignes – enveloppez-les avec la balise <code>&lt;pre&gt;</code>, pour plus de 10 lignes - utilisez une sandbox (<a href='https://plnkr.co/edit/?p=preview'>plnkr</a>, <a href='https://jsbin.com'>jsbin</a>, <a href='http://codepen.io'>codepen</a>…)</li></ul></div></div></div></div><div id="disqus_thread"></div><script>var disqus_config = function() { if (!this.page) this.page = {}; Object.assign(this.page, {"url":"https:\/\/fr.javascript.info\/mixins","identifier":"\/mixins"}); };</script><script>var disqus_shortname = "frjavascriptinfo";</script><script>var disqus_enabled = true;</script></div></script></main></div><div class="sidebar page__sidebar sidebar sidebar_sticky-footer"><button class="sidebar__toggle" data-sidebar-toggle></button><a class="map" href="/tutorial/map" data-action="tutorial-map" data-tooltip="Carte du tutoriel"></a><div class="sidebar__inner"><div class="sidebar__content"><div class="sidebar__section"><h4 class="sidebar__section-title">Chapitre</h4><nav class="sidebar__navigation"><ul class="sidebar__navigation-links"><li class="sidebar__navigation-link"><a class="sidebar__link" href="/classes">Classes</a></li></ul></nav></div><div class="sidebar__section"><h4 class="sidebar__section-title">Navigation des cours</h4><nav class="sidebar__navigation"><ul class="sidebar__navigation-links"><li class="sidebar__navigation-link"><a class="sidebar__link" href="#un-exemple-de-mixin">Un exemple de mixin</a></li><li class="sidebar__navigation-link"><a class="sidebar__link" href="#eventmixin">EventMixin</a></li><li class="sidebar__navigation-link"><a class="sidebar__link" href="#resume">Résumé</a></li></ul></nav></div><div class="sidebar__section"><nav class="sidebar__navigation"><ul class="sidebar__navigation-links"><li class="sidebar__navigation-link"><a class="sidebar__link" href="#comments">Commentaires</a></li></ul></nav></div><div class="sidebar__section"><div class="sidebar__section-title">Partager</div><a class="share share_tw sidebar__share" href="https://twitter.com/share?url=https%3A%2F%2Ffr.javascript.info%2Fmixins" rel="nofollow"></a><a class="share share_fb sidebar__share" href="https://www.facebook.com/sharer/sharer.php?s=100&amp;p[url]=https%3A%2F%2Ffr.javascript.info%2Fmixins" rel="nofollow"></a></div><div class="sidebar__section"><a class="sidebar__link" href="https://github.com/javascript-tutorial/fr.javascript.info/blob/master/1-js/09-classes/07-mixins" rel="nofollow">Editer sur GitHub</a></div></div></div></div></div></div><div class="page-footer"><ul class="page-footer__list"><li class="page-footer__item page-footer__item_copy">©&nbsp;2007—2025&nbsp; Ilya Kantor</li><li class="page-footer__item page-footer__item_about"><a class="page-footer__link" href="/about">à propos du projet</a></li><li class="page-footer__item page-footer__item_contact"><a class="page-footer__link" href="/about#contact-us">nous contacter</a></li></ul></div></body></html>

Pages: 1 2 3 4 5 6 7 8 9 10