mxins javascript с использованием `Object.assign`, оценка раньше, чем ожидалось

#javascript #mixins #getter

#javascript #mixins #средство получения

Вопрос:

У меня есть готовые микшины с установщиком и получателем:

 const dataentity_compnts_mixins = {
    set within_context(val_obj) {
        switch (val_obj["dataentity_morphsize"]) {
            case 'compact':
                this.shadow_wrapper.setAttribute(
                    "within-context", "compact_dataentity");
                break;

            case 'expanded':
                this.shadow_wrapper.setAttribute(
                    "within-context", "expanded_dataentity");
                break;
        }
    },

    get within_context() {
        const host_dataentity = this.parent_dataentity ||
            this.closest('independent-data-entity') ||
            this.closest('dependent-data-entity');
        this.parent_dataentity = host_dataentity;

        const context_dict = {
            "dataentity_morphsize": host_dataentity.getAttribute("morph-size"),
            "dataentity_role": host_dataentity.getAttribute("entity-role")
        };
        return context_dict;
    }
};
 

затем я использую Object.assign , чтобы объединить это с прототипом моего пользовательского элемента:

 Object.assign(IndividualviewEditor.prototype, dataentity_compnts_mixins); [1]
 

Я ожидал, что получатель и установщик не будут оцениваться до тех пор, пока не будут вызваны со this ссылкой на объект хоста, который в моем случае является IndividualviewEditor пользовательским элементом. Однако при запуске этого кода на моей веб-странице я получил сообщение об ошибке:

 Uncaught TypeError: this.closest is not a function ...
 

Я проверил стек вызовов, который предполагает, что средство получения вызывается строкой [1] .

Я сделал много поисковых запросов в Google и полностью заблудился. Этот геттер вычисляется при объединении с моим прототипом?? это намного раньше, чем я ожидал.

Ответ №1:

Object.assign копирует все собственные перечислимые свойства влево, что означает, что получатели извлекаются, а их возвращаемое значение копируется, но сама функциональность getter теряется.

 const mixin = {
  get random() {
    console.log('I am mixin', this === mixin);
    return Math.random();
  }
};

const reference = {};

Object.assign(reference, mixin);

console.log("-------"); 

С помощью этого кода вы будете читать в консоли I am mixin true , потому random что средство доступа извлекается во время копирования.

reference.random Действительно, он всегда будет указывать на одно и то же число, сгенерированное только во время Object.assign операции.

Для неглубокого копирования свойств вам нужно передать дескрипторы, а примитивами для этого являются Object.defineProperties и Object.getOwnPropertyDescriptors .

Давайте попробуем еще раз:

 const mixin = {
  get random() {
    console.log('I am mixin', this === mixin);
    return Math.random();
  }
};

const reference = {};

Object.defineProperties(
  reference,
  Object.getOwnPropertyDescriptors(mixin)
);

console.log("-------");

console.log(reference.random);
reference.random = 4; //no setter - nothing happens
console.log(reference.random); 

Первое, на что следует обратить внимание, это то, что вы ничего не будете читать в консоли, потому что средство доступа, ну, не доступно.

Однако всякий раз, когда вы получаете доступ reference.random , вы будете читать, что это не mixin контекст, и каждый раз он будет возвращать новое случайное значение.

Всякий раз, когда вы хотите определить микшины для классов или простых объектов, Object.defineProperties это правильный путь.