是否可以撤消Object.assign?

时间:2015-04-05 22:11:31

标签: ecmascript-6

我想使用Object.assign暂时用新方法“升级”对象,然后在我使用它们时删除这些方法。一个例子将澄清:

假设我们有一个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?

有没有办法实现这个目标?如果没有,我是否使用了错误的语言功能来实现我真正想要的功能 - 能够在运行时动态添加和删除对象方法,具体取决于上下文。

1 个答案:

答案 0 :(得分:2)

  

有没有办法实现这个目标?

有一些,但我认为它们都没有完全符合您的要求:

  • 使用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;
    }
    

    当你覆盖自己的方法/属性时,这并不好用。

  • 更改要扩展的对象的原型链

    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方法创建一个新对象。你没有&#34;通过丢掉临时的那个,再次使用旧的(不完全是你想到的用法模式,我猜?) - 你可以通过将旧的存储在一个属性中来隐藏这个事实并且&#34;解包&#34;使用unextend()函数。

    当然,这种简单而有效的模式的缺点是对临时对象的分配不起作用。他们会创建新的,自己的属性,而不是修改实际的对象,并且一旦你&#34;不进入&#34;就会被抛弃。这对您的avg方法无关紧要,甚至可以用于某些混音,但您可能不需要这样做。

  

如果没有,我使用的是错误的语言功能

很可能没有语言功能。

对于这种情况,最常见的建议是构造一个包装器对象(例如,围绕DOM对象),它充当用户和实际对象之间的代理。包装器的API与包装对象的API完全不同;这不是一个简单的&#34;扩展&#34;。