如何克隆JavaScript类实例?

Pet*_*tah 15 javascript jquery

如何克隆JavaScript类实例?

我尝试了普通的jQuery扩展,但这只是返回一个vanilla对象.我在堆栈上查看了许多其他答案,但找不到如何克隆实例.

function Parent(name) {
    this.name = name;
}

Parent.prototype.sayHello = function() {
    console.log('Hello my name is ' + this.name);
}

function Child(name) {
    Parent.call(this, name);
}

Child.prototype = Object.create(Parent.prototype);

var child = new Child('Billy');

var clone = $.extend(true, {}, child);
clone.name = 'Bob';

child.sayHello();
clone.sayHello();

console.log(child instanceof Child);
console.log(clone instanceof Child);
Run Code Online (Sandbox Code Playgroud)

http://jsfiddle.net/39gjA/

我希望克隆是深度/递归的.IE也克隆了作为对象的所有属性.

Ber*_*rgi 11

如何克隆JavaScript类实例?

如果在构造函数中大量使用闭包创建实例,则几乎不可能.我们现在可能永远不会设置哪些内部值,以及如何重现这样的设置.因此,最简单的方法是每个班级都提供一个clone知道该做什么的功能.

普通的jQuery扩展只返回一个vanilla对象

不一定,它会返回您传入的内容.使用

var clone = $.extend(true, Object.create(Object.getPrototypeOf(child)), child);
Run Code Online (Sandbox Code Playgroud)

相反,你的instanceof使用将正常工作.请注意,这true表示"深层"副本,可能是您想要的,也可能不是.此外,$.extend还将愉快地复制可枚举的继承属性,因此您可能需要使用更复杂的extend功能.

或者根本没有jQuery,只复制自己的,可枚举的属性,只使用浅拷贝:

var clone = Object.assign(Object.create(Object.getPrototypeOf(child)), child);
Run Code Online (Sandbox Code Playgroud)

但同样,并非所有对象都会以这种方式克隆,请参阅上面的第一点.


Jes*_*sse 8

这将创建一个具有相同原型(类)和相同属性(包括可枚举性/可写性/getter/setter 等)的对象的副本:

function clone(obj) {
  return Object.create(
    Object.getPrototypeOf(obj), 
    Object.getOwnPropertyDescriptors(obj) 
  );
}
Run Code Online (Sandbox Code Playgroud)

(见这里

它不一定适用于内置对象。例如Array.isArray(clone([]))is false,并clone(function () {})()表示它不是函数,但对于用户创建的对象(类实例或对象文字),它工作正常。

要进行深度克隆,您必须遍历属性描述符并递归地克隆值:

function deepClone(obj) {
  if (obj === null || typeof obj !== "object")
    return obj
  var props = Object.getOwnPropertyDescriptors(obj)
  for (var prop in props) {
    props[prop].value = deepClone(props[prop].value)
  }
  return Object.create(
    Object.getPrototypeOf(obj), 
    props
  )
}
Run Code Online (Sandbox Code Playgroud)