В чем разница между mixin () и extend () в библиотеках Javascript - PullRequest
16 голосов
/ 22 сентября 2011

Я просматриваю различные библиотеки и часто вижу всплывающую подсказку extension (), но я также вижу, что mixin () появляется.В YUI есть как миксины, так и расширения.

В чем разница между этими двумя понятиями?Когда я решу между миксином и расширением объекта?

Спасибо, Мэтт

Ответы [ 4 ]

16 голосов
/ 22 сентября 2011

Миксины не работают с instanceof, но расширяют их. Миксины допускают множественное наследование, но путем фальсификации, а не путем правильной цепочки прототипов.

Я покажу пример Ext-JS, но эта концепция применима к любой библиотеке классов, которая предоставляет миксины, все они просто копируют свойства в объект, а не соединяют в цепочку прототип.

Ext.define('Ext.Window', {
    extend: 'Ext.Panel',
    requires: 'Ext.Tool',
    mixins: {
        draggable: 'Ext.util.Draggable'
    }
});

Ext.Window instanceof Ext.Panel //true
Ext.Window instanceof Ext.util.Draggable // false

Миксины - отличный способ добавить некоторую функциональность к объекту, не прибегая к наследованию. Если вам нужно унаследовать что-то, чтобы получить какую-то функциональность, то вы не можете использовать функциональность двух классов . Многие люди считают, что это зло .

Ext-JS столкнулся с этой проблемой, когда хотел добавить функциональность Labelable к FieldSet и другим, которые не были введены как поля. Не было никакой возможности извлечь выгоду из поведения Labelable внутри Field, поскольку они не могли расширять Field, поскольку в нем также было все входное поведение.

6 голосов
/ 15 ноября 2013

Метод extends довольно распространен среди библиотек JavaScript и обычно представляет собой метод, который просто позволяет потребляющему коду добавлять все «собственные» свойства и методы одного или нескольких объектов в целевой объект.Код обычно довольно прост: перебирайте все собственные ключи каждого аргумента, кроме первого, и копируйте значение, сохраненное там, в первый аргумент.

«Mixin» относится к шаблону проектирования, в котором вы используете один объекткак своего рода контейнер для определенного набора свойств и методов, которые вы хотите использовать для множества объектов в вашей системе.Например, у вас могут быть средства получения и установки ширины и высоты, которые могут применяться ко всем компонентам пользовательского интерфейса в вашем приложении, и поэтому вы должны создать, в случае JavaScript, либо функцию, для которой можно создать экземпляр «new», либо литерал объекта, которыйдержит эти методы.Затем вы можете использовать функцию типа "extends", чтобы скопировать эти методы на любое количество объектов в вашей системе.

В Underscore есть метод mixin, который по сути является просто расширением, где все переданные в объектах методы являютсядобавлен базовый объект подчеркивания для использования в цепочке.jQuery делает то же самое с методом расширения jQuery.fn.

Лично мне нравится сохранять расширение как есть, поведение типа «копировать все из этих объектов в этот объект», имея отдельный метод mixin, который вместо этогопринимает только один исходный объект, а затем обрабатывает все дальнейшие аргументы как имена свойств и методов для копирования (если передаются только цель и источник без дополнительных аргументов, тогда он просто действует как расширение из одного источника).

например

function mixin(target, source) {
    function copyProperty(key) {
        target[key] = source[key];
    }

    if (arguments.length > 2) {
        // If there are arguments beyond target and source then treat them as
        // keys of the specific properties/methods that should be copied over.
        Array.prototype.slice.call(arguments, 2).forEach(copyProperty);
    } else {
        // Otherwise copy all properties/methods from the source to the target.
        Object.keys(source).forEach(copyProperty);
    }
}
2 голосов
/ 18 декабря 2012

Вы можете определенно создавать миксины, используя extends.

Миксины дают все преимущества множественного наследования без иерархии (прототип наследования в JavaScript). Они оба позволяют повторно использовать интерфейс (или набор функций) для нескольких объектов. С миксинами не сталкивайтесь с «проблемой алмазов», с которой вы можете столкнуться в отношениях родитель-потомок.

Проблема с алмазом возникает, когда один объект наследует одну и ту же функцию (или даже имя функции) от двух объектов. Зачем? Если один из этих двух объектов изменил функцию, добавив функциональность (т. Е. В Java, называемую «супер»), JavaScript больше не знает, как интерпретировать / комбинировать эти два метода. Миксины - это способ избежать этой иерархии. Они определяют функциональность, которую вы можете прикрепить где угодно. Миксины также обычно не содержат собственных данных.

Так что я мог бы, например, написать миксин с $.extend() в jQuery. var newmixin = $.extend({}, mixin1, mixin2) объединит два интерфейса и сгладит их (перезаписать конфликты имен).

Вот 3 вещи для рассмотрения:

  1. Имеет ли комбинация двух интерфейсов "иерархия", т.е. отношения родитель / ребенок. В JavaScript это будет означать наследование прототипа.
  2. Функции копируются или на них ссылаются? Если исходный метод изменится, изменятся ли и унаследованные методы?
  3. Что происходит, когда два метода с одинаковым именем объединяются? И как решаются эти конфликты?
0 голосов
/ 22 сентября 2011

Изменить для ясности: Иногда это одно и то же, а иногда нет; mixin - это имя шаблона, используемого для повторного использования функций между несколькими объектами, а extension - это больше алгоритм / метод, используемый для этого. Есть случаи, когда они идентичны (например, подчеркивание _.extend) и случаи, когда они различаются (расширение backbone.js).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...