是否可以撤消 Object.assign?
Is it possible to undo Object.assign?
我想暂时使用 Object.assign
到 "upgrade" 具有新方法的对象,然后在使用完这些方法后删除它们。一个例子将说明:
假设我们有一个 mixin 允许我们计算数组的平均值:
var ArrayUtilMixin = {
avg() {
let sum = this.reduce( (prev, v) => {return prev + v}, 0);
return sum / this.length;
}
};
我们的客户端代码是这样使用的:
let myArr = [0,3,2,4,88];
// now I am in a context where I want to average this array,
// so I dynamically add the ability with Object.assign
Object.assign(myArr, ArrayUtilMixin);
let avg = myArr.avg();
// do some stuff here with the average
// now we're done, we want declutter the myArr object
// and remove the no longer needed avg() method
Object.unassign(myArr, ArrayUtilMixin); // <-- CAN WE DO THIS SOMEHOW?
有什么办法可以做到吗?如果不是,我是否使用了错误的语言功能来实现我真正想要的——在运行时根据上下文动态添加和删除对象方法的能力。
Is there any way to accomplish this?
有一些,但我认为其中 none 完全符合您的要求:
使用Object.assign
,然后delete
新属性
Object.unassign = function(o, mixin) {
for (var p in mixin)
delete o[p]; // deletes own properties only, so don't fear
return o;
}
当然,当您覆盖自己的 methods/properties 时,这将无法正常工作。
更改要扩展的对象的原型链
function extend(o, mixin) {
var m = Object.assign({}, mixin);
Object.setPrototypeOf(m, Object.getPrototypeOf(o));
Object.setPrototypeOf(o, m);
return o;
}
function unextend(o) {
Object.setPrototypeOf(o, Object.getPrototypeOf(Object.getPrototypeOf(o)));
return o;
}
这种方法的优点是自有属性保留自有属性,因此对对象的赋值将照常进行。有一些语言支持这种模式(并将其与多重继承相结合),但我不确定它的实际效果如何。当然,在 JavaScript.
中修改原型链是一个非常糟糕的主意
添加到原型链
function extended(o, mixin) {
return Object.assign(Object.create(o), mixin);
}
这将使用继承自实际对象的 mixin 方法创建一个新对象。你 "unextend" 只是扔掉临时的,然后再次使用旧的(我猜这不完全是你想到的使用模式?) - 你可以通过将旧的存储在 属性 和 "unwrap" 具有 unextend()
函数。
当然,这种简单而高效的模式的缺点是对临时对象的赋值不起作用。他们会创建新的、自己的属性而不是修改实际的对象,并且一旦你 "unextend" 就会被扔掉。这对您的 avg
方法无关紧要,甚至可以用于某些混入,但您可能不希望这样。
If not, am I using the wrong language feature
很可能没有针对此的语言功能。
对于这种情况,最常见的建议是构造一个包装器对象(例如围绕 DOM 个对象),它充当用户和实际对象之间的代理。包装器的 API 与包装对象的完全不同;这不是简单的 "extension".
我想暂时使用 Object.assign
到 "upgrade" 具有新方法的对象,然后在使用完这些方法后删除它们。一个例子将说明:
假设我们有一个 mixin 允许我们计算数组的平均值:
var ArrayUtilMixin = {
avg() {
let sum = this.reduce( (prev, v) => {return prev + v}, 0);
return sum / this.length;
}
};
我们的客户端代码是这样使用的:
let myArr = [0,3,2,4,88];
// now I am in a context where I want to average this array,
// so I dynamically add the ability with Object.assign
Object.assign(myArr, ArrayUtilMixin);
let avg = myArr.avg();
// do some stuff here with the average
// now we're done, we want declutter the myArr object
// and remove the no longer needed avg() method
Object.unassign(myArr, ArrayUtilMixin); // <-- CAN WE DO THIS SOMEHOW?
有什么办法可以做到吗?如果不是,我是否使用了错误的语言功能来实现我真正想要的——在运行时根据上下文动态添加和删除对象方法的能力。
Is there any way to accomplish this?
有一些,但我认为其中 none 完全符合您的要求:
使用
Object.assign
,然后delete
新属性Object.unassign = function(o, mixin) { for (var p in mixin) delete o[p]; // deletes own properties only, so don't fear return o; }
当然,当您覆盖自己的 methods/properties 时,这将无法正常工作。
更改要扩展的对象的原型链
function extend(o, mixin) { var m = Object.assign({}, mixin); Object.setPrototypeOf(m, Object.getPrototypeOf(o)); Object.setPrototypeOf(o, m); return o; } function unextend(o) { Object.setPrototypeOf(o, Object.getPrototypeOf(Object.getPrototypeOf(o))); return o; }
这种方法的优点是自有属性保留自有属性,因此对对象的赋值将照常进行。有一些语言支持这种模式(并将其与多重继承相结合),但我不确定它的实际效果如何。当然,在 JavaScript.
中修改原型链是一个非常糟糕的主意
添加到原型链
function extended(o, mixin) { return Object.assign(Object.create(o), mixin); }
这将使用继承自实际对象的 mixin 方法创建一个新对象。你 "unextend" 只是扔掉临时的,然后再次使用旧的(我猜这不完全是你想到的使用模式?) - 你可以通过将旧的存储在 属性 和 "unwrap" 具有
unextend()
函数。当然,这种简单而高效的模式的缺点是对临时对象的赋值不起作用。他们会创建新的、自己的属性而不是修改实际的对象,并且一旦你 "unextend" 就会被扔掉。这对您的
avg
方法无关紧要,甚至可以用于某些混入,但您可能不希望这样。
If not, am I using the wrong language feature
很可能没有针对此的语言功能。
对于这种情况,最常见的建议是构造一个包装器对象(例如围绕 DOM 个对象),它充当用户和实际对象之间的代理。包装器的 API 与包装对象的完全不同;这不是简单的 "extension".