JavaScript'те сиз бир гана объекттен мураска аласыз. Объекттин бирдиктүү бар [[Prototype]]
. Ал эми класс бир гана классты кеңейте алат.
Кээде ал бизди чектеп коюшу мүмкүн. Мисалы, бизде класс StreetSweeper
жана класс бар Bicycle
жана биз алардын аралашмасын түзгүбүз келет: StreetSweepingBicycle
.
Же бизде колдонуучуларды ишке ашырган класс жана окуяларды ишке ашырган User
класс бар. Колдонуучулар окуяларды оңой эле өчүрө алышы үчүн класстын функцияларын кошкубуз EventEmitter
келет .EventEmitter
User
Мындай учурлар үчүн "булгануулар" бар.
Википедиядан алынган аныктама боюнча, ыпластык – бул башка класстарда колдонууга арналган жана ыпластыктан мурассыз класс.
Башка сөз менен айтканда, миксин белгилүү бир жүрүм-турумду ишке ашыруу ыкмаларын аныктайт. Биз миксинди өз алдынча колдонбойбуз, бирок аны башка класстарга функция кошуу үчүн колдонобуз.
Мисал аралашма
JavaScript'те миксинди ишке ашыруунун эң жөнөкөй жолу - бул кандайдыр бир класстын прототипине оңой кошула турган пайдалуу методдор менен объект түзүү.
Төмөндөгү мисалда миксин класстын объектилерине сүйлөшүү мүмкүнчүлүгүн sayHiMixin
берген ыкмаларга ээ :User
@A@// примесь
let sayHiMixin = {
sayHi() {
alert(`Привет, ${this.name}`);
},
sayBye() {
alert(`Пока, ${this.name}`);
}
};
// использование:
class User {
constructor(name) {
this.name = name;
}
}
// копируем методы
Object.assign(User.prototype, sayHiMixin);
// теперь User может сказать Привет
new User("Вася").sayHi(); // Привет, Вася!@A@
Бул мурас эмес, жөн гана көчүрүү ыкмалары. Ошентип, класс User
башка класстан мурасташы мүмкүн, бирок ошондой эле башка ыкмаларды "аралаштырган" миксиндерди камтыйт, мисалы:
@A@class User extends Person {
// ...
}
Object.assign(User.prototype, sayHiMixin);@@A@
Булганычтар бири-бирин мурастай алышат.
Төмөнкү мисалда, sayHiMixin
ал мураска алат sayMixin
:
@A@let sayMixin = {
say(phrase) {
alert(phrase);
}
};
let sayHiMixin = {
__proto__: sayMixin, // (или мы можем использовать Object.create для задания прототипа)
sayHi() {
// вызываем метод родителя
super.say(`Привет, ${this.name}`); // (*)
},
sayBye() {
super.say(`Пока, ${this.name}`); // (*)
}
};
class User {
constructor(name) {
this.name = name;
}
}
// копируем методы
Object.assign(User.prototype, sayHiMixin);
// теперь User может сказать Привет
new User("Вася").sayHi(); // Привет, Вася!@A@
super.say()
Ата-энелик ыкмадан sayHiMixin
(белгиленген сызыктар ) чакырганда (*)
, бул ыкма класста эмес, миксиндин өзүнүн прототибинен изделет.
Бул ыкмалар башында түзүлгөн, sayHi
анткени . Алар көчүрүлгөн болсо да, алардын ички касиеттери жогорудагы сүрөттө көрсөтүлгөндөй, тиешелүү @A@.sayBye
sayHiMixin
[[HomeObject]]
sayHiMixin@A@
super
Ал ата-эне ыкмаларын издегендиктен , [[HomeObject]].[[Prototype]]
бул sayHiMixin.[[Prototype]]
эмес дегенди билдирет User.[[Prototype]]
.
eventmixin
Браузерди иштеп чыгуудагы көптөгөн объекттер (жана гана эмес) маанилүү жөндөмгө ээ - алар окуяларды түзө алышат. Окуялар ага кызыккандардын бардыгына маалымат жеткирүүнүн эң сонун жолу. Келгиле, ар кандай класска/объектке окуяны башкаруу функциясын кошууну жеңилдеткен миксин түзөлү.
.trigger(name, [data])
Миксин окуяны күйгүзүү ыкмасын кошот . Аргументname
- бул окуянын аталышы, андан кийин окуянын маалыматтары менен башка аргументтер болушу мүмкүн..on(name, handler)
Ал ошондой эле аталган аталыш менен окуя үчүн иштеткичти дайындаган ыкманы кошот . Иштетүүчү көрсөтүлгөн аталыштагы окуя болгондо чакырылатname
жана бул жерден маалыматтарды алат.trigger
..off(name, handler)
...жана көрсөтүлгөн окуя үчүн иштеткичти жок кылган ыкма .
Бардык аралаштыруу ыкмалары кошулгандан кийин, объект колдонуучу жеке аккаунтка киргенден кийин user
окуяны түзө алат . "login"
Жана башка объект, мисалы, calendar
бул окуяны колдонууга кирген колдонуучуга ага тиешелүү календарды көрсөтүү үчүн колдоно алат.
Же menu
ал меню пункту тандалганда окуяны иштете алат "select"
жана башка объекттер ошол окуяга жооп берүү үчүн иштеткичтерди дайындай алат ж.б.у.с.
Бул жерде микс коду:
@A@let eventMixin = {
/**
* Подписаться на событие, использование:
* 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);
},
/**
* Отменить подписку, использование:
* menu.off('select', handler)
*/
off(eventName, handler) {
let handlers = this._eventHandlers && this._eventHandlers[eventName];
if (!handlers) return;
for (let i = 0; i < handlers.length; i++) {
if (handlers[i] === handler) {
handlers.splice(i--, 1);
}
}
},
/**
* Сгенерировать событие с указанным именем и данными
* this.trigger('select', data1, data2);
*/
trigger(eventName, ...args) {
if (!this._eventHandlers || !this._eventHandlers[eventName]) {
return; // обработчиков для этого события нет
}
// вызовем обработчики
this._eventHandlers[eventName].forEach(handler => handler.apply(this, args));
}
};@A@
Ошентип, бизде 3 ыкма бар:
-
.on(eventName, handler)
handler
– берилген ат менен окуяны башкаруу функциясын дайындайт . Иштетүүчүлөр касиетте сакталат_eventHandlers
, ал объект болуп саналат, анда окуянын аты ачкыч жана иштеткичтердин массивинде маани берилет. -
.off(eventName, handler)
– функцияны иштетүүчүлөрдүн тизмесинен алып салат. -
.trigger(eventName, ...args)
- окуяны чыгарат: бардык дайындалган иштеткичтер чакырылып_eventHandlers[eventName]
,...args
аларга аргумент катары берилет.
Колдонуу:
@A@// Создадим класс
class Menu {
choose(value) {
this.trigger("select", value);
}
}
// Добавим примесь с методами для событий
Object.assign(Menu.prototype, eventMixin);
let menu = new Menu();
// Добавить обработчик, который будет вызван при событии "select":
menu.on("select", value => alert(`Выбранное значение: ${value}`));
// Генерирует событие => обработчик выше запускается и выводит:
menu.choose("123"); // Выбранное значение: 123@A@
Эми бизде окуяга кызыккан код болсо "select"
, анда ал аны менен уга алат menu.on(...)
.
Жана eventMixin
бул кыймыл-аракетти мурастоо чынжырына тоскоолдук кылбастан каалаган класска кошууну жеңилдетет.
Бардыгы
Mixin объектиге багытталган программалоонун жалпы термини: башка класстар үчүн методдорду камтыган класс.
Кээ бир башка тилдер бир нече мураска жол берет. JavaScript бир нече тукум куучулукту колдобойт, бирок миксиндер менен биз ыкмаларды прототикке көчүрүү менен окшош нерсени ишке ашыра алабыз.
Биз жогоруда айткандай, окуяларды башкаруу сыяктуу класстардын функцияларын кеңейтүү үчүн миксиндерди колдоно алабыз.
Миксиндер учурдагы класстык методдорду кайра жазса, конфликттерди жаратышы мүмкүн. Муну эстен чыгарбоо жана аралашма ыкмаларына ат тандоодо этият болуу зарыл.