Кастомные JavaScript коллекции в стиле Laravel 5

Категория: JavaScript

Создаем и расширяем кастомные коллекции моделей/записей на JavaScript в стиле Laravel 5.

Чтобы не выдумывать ничего нового, за основу берем библиотеку collect.js:

npm install -S collect.js

Библиотека предоставляет метод macro() для глобального добавления новых методов в прототип объекта класса (по факту, функции) Collection:

collect().macro('newCollectionMethod', functionName);

Проблемы и ограничения:

  1. Метод macro() не позволяет расширять наши кастомные классы EntityCollection (или я что-то упустил).
  2. Мы не можем наследовать (extends) класс Collection в EntityCollection поскольку большинство методов коллекции возвращают новый объект типа Collection, а не наш EntityCollection.

Я остановился на следующем решении - в конструкторе нашей EntityCollection расширяем прототип класса свойствами/методами объекта типа Collection.

Пример класса коллекции:

import UserModel from './UserModel';
import collect from 'collect.js';

/**
 * @class UserCollection
 * @property {Array} items
 */
class UserCollection {
    constructor(items) {
        items = items || [];

        let collectionProperties = Object.getPrototypeOf(collect());
        Object.assign(this, collectionProperties);

        this.items = items.map(function(item, i) {
            return new UserModel(item);
        });
    }

    customCollectionMethod() {
        console.log('customCollectionMethod');

        // @note See returns logic in origin methods! >>
        // return new this.constructor(collection);
    }
}

export default MissionCollection;

Свойства прототипа Collection можно получить разными способами:

let collectionProperties = collect().__proto__;
let collectionProperties = (new Collection).__proto__;
let collectionProperties = Object.getPrototypeOf(collect());

Расширить прототип нашей коллекции, возможно, правильнее было бы так (документация):

Object.defineProperties(UserCollection, props);

Но, нужно формировать специфический объект расширяемых свойств.

Или так (не поддерживает Safari) (документация):

Object.setPrototypeOf(UserCollection, collect().__proto__);

А есть еще Object.create:

Object.create(proto[, propertiesObject]);

Но есть ли необходимость усложнять? Не готов ничего утверждать, увы, нет времени для выяснения.

Замечания, предложения, конструктивная критика - приветствуются.

Успехов в разработке!

#collect.js, #javascript collection, #javascript collection like laravel 5

категория: JavaScript