Javascript克隆对象失去了原型函数

saz*_*azr 13 javascript

我试图在Javascript中克隆一个对象.我已经创建了自己的"类",它具有原型功能.

我的问题:当我克隆一个对象时,克隆无法访问/调用任何原型函数.

当我去访问克隆的原型函数时,我收到一个错误:

clone.render不是一个函数

你能告诉我如何克隆一个对象并保持其原型功能

这个简单的JSFiddle演示了我得到的错误:http://jsfiddle.net/VHEFb/1/

function cloneObject(obj) 
{
   // Handle the 3 simple types, and null or undefined
   if (null == obj || "object" != typeof obj) return obj;

   // Handle Date
   if (obj instanceof Date) {
     var copy = new Date();
     copy.setTime(obj.getTime());
     return copy;
   }

   // Handle Array
   if (obj instanceof Array) {
     var copy = [];
     for (var i = 0, len = obj.length; i < len; ++i) {
         copy[i] = cloneObject(obj[i]);
     }
     return copy;
   }

   // Handle Object
   if (obj instanceof Object) {
     var copy = {};
     for (var attr in obj) {
         if (obj.hasOwnProperty(attr)) copy[attr] = cloneObject(obj[attr]);
     }
     return copy;
   }

   throw new Error("Unable to copy obj! Its type isn't supported.");
}

function MyObject(name)
{
    this.name = name;
    // I have arrays stored in this object also so a simple cloneNode(true) call wont copy those
    // thus the need for the function cloneObject();
}

MyObject.prototype.render = function()
{
    alert("Render executing: "+this.name);
}

var base  = new MyObject("base");
var clone = cloneObject(base);
clone.name = "clone";
base.render();
clone.render();  // Error here: "clone.render is not a function"
Run Code Online (Sandbox Code Playgroud)

Rob*_*obG 7

关于代码的一些评论:

>    if (obj instanceof Date) {
>      var copy = new Date();
>      copy.setTime(obj.getTime());
Run Code Online (Sandbox Code Playgroud)

可:

if (obj instanceof Date) {
  var copy = new Date(obj);
Run Code Online (Sandbox Code Playgroud)

>    if (obj instanceof Array) {
Run Code Online (Sandbox Code Playgroud)

如果obj是来自另一个全局上下文的数组,例如iFrame,则返回false.考虑:

     if (o && !(o.constructor.toString().indexOf("Array") == -1))

>      var copy = [];
>      for (var i = 0, len = obj.length; i < len; ++i) {
>          copy[i] = cloneObject(obj[i]);
>      }
Run Code Online (Sandbox Code Playgroud)

使用slice以下方法可以更有效,更准确地将一个数组的索引复制到另一个数组:

      var copy = obj.slice();
Run Code Online (Sandbox Code Playgroud)

虽然您会遗漏可能已添加的非数字的任何其他属性.循环超过0到长度将为克隆添加稀疏数组中不存在的属性(例如,精简将成为未定义的成员).

至于克隆部分......

在零件复制对象属性中,它将所有属性(包括原始[[Prototype]]链上的属性)直接复制到"克隆"对象.真正"克隆"对象的唯一方法是将其设置[[Prototype]]为与原始对象相同的对象,然后将原始(可过滤的hasOwnProperty)上的可枚举属性复制到克隆.

第二部分是微不足道的,第一部分是不是(在一般意义上),因为你不能保证对象的constructor属性引用它的对象prototype就是它[[Prototype]],也不能保证构造函数的原型并没有改变(即是在此期间,一个不同的对象).

你可以得到的最接近的是使用Lasse Reichstein Nielsenclone(由Douglas Crockford推广beget),它使原始对象[[Prototype]]成为克隆,然后将构造函数设置为相同的对象.虽然您可能仍需要复制可枚举的属性,但它们会掩盖原始的同名属性.

所以你真的只能在受限制的上下文中克隆一个对象,你不能一般地做.通常,这种实现会导致您无需一般性地克隆对象的设计.