Loading...

Aралашмалар

Aралашмалар

 

JavaScript'те сиз бир гана объекттен мураска аласыз. Объекттин бирдиктүү бар [[Prototype]]. Ал эми класс бир гана классты кеңейте алат.

Кээде ал бизди чектеп коюшу мүмкүн. Мисалы, бизде класс StreetSweeperжана класс бар Bicycleжана биз алардын аралашмасын түзгүбүз келет: StreetSweepingBicycle.

Же бизде колдонуучуларды ишке ашырган класс жана окуяларды ишке ашырган Userкласс бар. Колдонуучулар окуяларды оңой эле өчүрө алышы үчүн класстын функцияларын кошкубуз EventEmitterкелет .EventEmitterUser

Мындай учурлар үчүн "булгануулар" бар.

Википедиядан алынган аныктама боюнча, ыпластык – бул башка класстарда колдонууга арналган жана ыпластыктан мурассыз класс.

Башка сөз менен айтканда, миксин белгилүү бир жүрүм-турумду ишке ашыруу ыкмаларын аныктайт. Биз миксинди өз алдынча колдонбойбуз, бирок аны башка класстарга функция кошуу үчүн колдонобуз.

Мисал аралашма

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@.sayByesayHiMixin[[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 ыкма бар:

  1. .on(eventName, handler)handler– берилген ат менен окуяны башкаруу функциясын дайындайт . Иштетүүчүлөр касиетте сакталат _eventHandlers, ал объект болуп саналат, анда окуянын аты ачкыч жана иштеткичтердин массивинде маани берилет.

  2. .off(eventName, handler)– функцияны иштетүүчүлөрдүн тизмесинен алып салат.

  3. .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 бир нече тукум куучулукту колдобойт, бирок миксиндер менен биз ыкмаларды прототикке көчүрүү менен окшош нерсени ишке ашыра алабыз.

Биз жогоруда айткандай, окуяларды башкаруу сыяктуу класстардын функцияларын кеңейтүү үчүн миксиндерди колдоно алабыз.

Миксиндер учурдагы класстык методдорду кайра жазса, конфликттерди жаратышы мүмкүн. Муну эстен чыгарбоо жана аралашма ыкмаларына ат тандоодо этият болуу зарыл.