【问题标题】:javascript mxins using `Object.assign`, evaluation earlier than expectedjavascript mxins 使用 `Object.assign`,比预期更早的评估
【发布时间】:2021-01-14 07:57:00
【问题描述】:

我有 fowlling mixin,带有一个 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 上进行了多次搜索,但完全迷失了方向。这个吸气剂在合并到我的原型时被评估??这比我预期的要早得多。

【问题讨论】:

    标签: javascript mixins getter


    【解决方案1】:

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

    当您想为类或普通对象定义 mixin 时,Object.defineProperties 是您的最佳选择。

    【讨论】:

      猜你喜欢
      • 2021-10-24
      • 1970-01-01
      • 1970-01-01
      • 2017-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多