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.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
上下文,它将 return 一个新的每次都是随机值。
每当你想为 类 或普通对象定义 mixin 时,Object.defineProperties
就是你要走的路。
我有 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.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
上下文,它将 return 一个新的每次都是随机值。
每当你想为 类 或普通对象定义 mixin 时,Object.defineProperties
就是你要走的路。