将实例克隆到独立对象

时间:2015-07-05 23:31:59

标签: javascript class object

我有一个董事会成员:

var board = new Board();

我想要修复电路板并在新电路板上运行movePiece功能:

var newBoard = board;
newBoard.movePiece('4a', '3b');

由于我只是分配它,boardnewBoard都会有移动的部分。

如何克隆棋盘以创建一个名为newBoard的精确副本,我可以移动该棋子并且原始棋盘将保持不变?

我尝试了几种不同的方法,例如:

Object.assign({}, orig)

function clone(orig) {
    let origProto = Object.getPrototypeOf(orig);
    return Object.assign(Object.create(origProto), orig);
}

来自http://www.2ality.com/2014/12/es6-oop.html

1 个答案:

答案 0 :(得分:6)

为任意对象创建可靠克隆的唯一方法是在该对象上编写一个方法,该方法接受一个实例并从原始实例的属性创建一个新实例。

这是因为外部代理无法确切知道如何处理每个实例变量(需要分配的内容,需要复制的内容等等),并且也可以拥有私有实例变量。因此,只需编写一个新方法来创建一个新对象并复制相关属性或一个构造函数,该方法将获取另一个对象并执行相同操作。

有可能有一个对象可以将所有属性分配给新实例(如果所有属性都是基元),但通常情况并非如此,因此需要应用更多智能来确定如何最佳分配每个属性到新克隆。而且,一个对象可能有私有实例变量(闭包变量),这些变量也可能必须从其他方法中手动处理。

这是一个相对简单的对象的示例,其中只有一个需要复制的数组。这个支持通过构造函数或克隆方法创建克隆:

function CallbackList(otherObj) {
    // if another object is passed to the constructor, then initialize this
    // new instance to be a copy
    if (otherObj) {
        // copy the array from the other instance
        this.list = otherObj.list.slice(0);
    } else {
        // initalize empty list
        this.list = [];
    }
}

CallbackList.prototype = {
    addListener: function(fn) {
        this.list.push(fn);
    },
    removeListener: function(fn) {
        for (var i = this.list.length - 1; i >= 0; i--) {
           if (this.list[i] === fn) {
              this.list.splice(i, 1);
           }
        }
    },
    fire: function(/* pass args here */) {
        var args = Array.prototype.slice.call(arguments);
        this.list.forEach(function(fn) {
            fn.apply(null, args);
        });
    },
    clone: function() {
        return new CallbackList(this);
    }
};

要理解为什么需要专门为您的对象构建的自定义代码来创建克隆,以下是您可能必须以特定于对象的方式处理的实例数据中的一些内容:

  1. 对DOM对象的引用。也许,克隆应该具有相同的引用(只是复制),或者可能需要创建一个新的DOM对象并将其插入到DOM中。
  2. 引用其他对象。也许新克隆应该具有相同的引用,或者可能需要为克隆创建新对象。
  3. 阵列。如果它是对共享数组的引用,则两个克隆都应指向同一个数组。如果它应该是每个对象独立的唯一实例数据,则需要复制该数组。如果数组本身包含对象,那么对数组的内容也有相同的问题。
  4. 对象。与数组相同的问题。
  5. 关闭变量(私有的实例变量)。与上面提到的对象属性相同的问题。