javascript mxins 使用 `Object.assign`,评估早于预期

javascript mxins using `Object.assign`, evaluation earlier than expected

我有 fowling mixins,有一个 setter 和一个 getter:

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]

我原以为 getter 和 setter 在使用 this 引用主机对象调用之前不会被评估,在我的例子中是 IndividualviewEditor 自定义元素。但是,当 运行 这段代码出现在我的网页上时,我得到一个错误:

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

我检查了调用堆栈,这表明 getter 被行 [1].

调用

我在 google 上进行了多次搜索,但完全迷失了方向。这个 getter 在合并到我的原型中时被评估?这比我预期的要早得多。

Object.assign 将所有自己的可枚举属性复制到左侧,这意味着 getter 被检索,并且它们的 returned 值被复制,但是 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.definePropertiesObject.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 上下文,它将 return 一个新的每次都是随机值。

每当你想为 类 或普通对象定义 mixin 时,Object.defineProperties 就是你要走的路。