是否可以撤消Object.assign? [英] Is it possible to undo Object.assign?

查看:131
本文介绍了是否可以撤消Object.assign?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 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]; 
//现在我在一个上下文中,我想平均这个数组,
//所以我动态地添加与Object.assign的能力
Object.assign(myArr,ArrayUtilMixin);
let avg = myArr.avg();
//在这里做一些平均的
//现在我们完成了,我们要声明myArr对象
//并删除不再需要的avg()方法

Object.unassign(myArr,ArrayUtilMixin); //< - 我们可以这么做吗

有没有办法完成这个?如果没有,我使用错误的语言功能,我真正想要的 - 这种能力,在运行时根据上下文动态添加和删除对象方法。

解决方案


有没有办法完成这个?


但是我觉得他们中没有一个完全符合你想要做的:




  • 使用 Object.assign ,然后删除新属性

      Object.unassign = function(o,mixin){
    for(var p in mixin)
    delete o [p]; //只删除自己的属性,所以不要害怕
    return o;
    }

    当您覆盖自己的方法/属性时,这不行


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

      function extend(o,mixin){
    var m = Object.assign({},mixin);
    Object.setPrototypeOf(m,Object.getPrototypeOf(o));
    Object.setPrototypeOf(o,m);
    return o;
    }
    函数unextend(o){
    Object.setPrototypeOf(o,Object.getPrototypeOf(Object.getPrototypeOf(o)));
    return o;
    }

    这种方法的优点是自己的属性保留自己的属性,该对象将照常工作。有些语言支持这种模式(并将其与多个继承相结合),但我不知道它的效果如何。当然,修改原型链在JavaScript中是一个非常糟糕的主意。


  • 在原型链前加入



    函数扩展(o,mixin){pre> {
    return Object.assign(Object.create(o),mixin);
    }

    这将使用从实际对象继承的mixin方法创建一个新对象。你会通过抛弃临时的放弃,再次使用旧的(不完全是你想到的使用模式) - 你可以通过将旧的存储在属性中来隐藏这个事实,并且展开 unextend()函数。



    当然,这种简单有效的模式的缺点是临时对象的分配不起作用。他们将创建新的自己的属性,而不是修改实际的对象,并且一旦你取消延伸就被丢弃。这对您的 avg 方法无关紧要,甚至可以用于某些混合,但您可能不希望这样。





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


很有可能没有这个语言功能。



对于这种情况,最常见的建议是构建一个包装器对象DOM对象),用作用户和实际对象之间的代理。包装的API与包装对象的API完全不同;这不是一个简单的扩展。


I'd like to use Object.assign to "upgrade" an object with new methods temporarily, and then remove those methods when I'm done using them. An example will clarify:

Say we have a mixin that allows us to calculate the average of an array:

var ArrayUtilMixin = {
  avg() {
    let sum = this.reduce( (prev, v) => {return prev + v}, 0);
    return sum / this.length;
  }
};

Our client code uses this like so:

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? If not, am I using the wrong language feature for what I really want -- that ability to dynamically add and remove object methods at runtime, depending on context.

解决方案

Is there any way to accomplish this?

There are some, but I think none of them does exactly what you want to do:

  • use Object.assign, then afterwards delete the new properties

    Object.unassign = function(o, mixin) {
        for (var p in mixin)
            delete o[p]; // deletes own properties only, so don't fear
        return o;
    }
    

    This doesn't work well when you have overwritten own methods/properties of course.

  • alter the prototype chain of the object you want to extend

    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;
    }
    

    The advantage of this approach is that own properties stay own properties, so assignments on the object will work as usual. There are some languages that endorse this pattern (and combine it with multiple inheritance), but I'm not sure how well it really works. Of course, modifying the prototype chain is a really bad idea in JavaScript.

  • prepend to the prototype chain

    function extended(o, mixin) {
        return Object.assign(Object.create(o), mixin);
    }
    

    This creates a new object with the mixin methods that inherits from the actual object. You'd "unextend" by just throwing away the temporary one, and use the old again (not exactly the usage pattern you had in mind I guess?) - you can hide this fact by storing the old one in a property and "unwrap" with a unextend() function.

    Of course, the drawback of this otherwise simple and efficient pattern is that assignments to the temporary object don't work. They would create new, own properties instead of modifying the actual object, and would get thrown away once you "unextend". This doesn't matter for your avg method, and can even be utilised for some mixins, but you might not want this.

If not, am I using the wrong language feature

It's quite possible that there is no language feature for this.

The most common advice for cases like this is to construct a wrapper object (e.g. around DOM objects), which acts as a proxy between the user and the actual object. The API of the wrapper is completely different from the wrapped object's one though; this is not a simple "extension".

这篇关于是否可以撤消Object.assign?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆