Js 对象拷贝

Js 对象拷贝

对象的引用在js里面实在的太常见了。如果不注意这个问题,则往往会犯一些小白一样的错误。比如:

var pa = {
  name: 'huasheng',
  age: '20',
  address: {
    province: 'zzz',
    city: 'aaa'
  }
};

function test(param){
  var addr = param.address;
  addr.city = "bbb";
}

test(obj);

console.log(obj.address.city); // bbb
// 这里函数test里面的 addr = param.address 其实就产生了一个引用
// 本来以为的是把param的address重新赋给一个变量 addr,然后修改 addr 里面的值,不去影响param
// 但是实验结果发现,addr 和 param.address 两个其实是一个东西。

关于Js变量引用的问题,其实就是数据类型的问题。在Js里面,有两种数据类型:基础类型和引用类型

其中,Number, Boolean, String都是基础类型,引用类型包括:Object, Array, Function

大家也可以参考一下这篇文章:http://www.cnblogs.com/diva/

既然发现了问题,那当然要来解决问题。(下面主要针对的是Object和Array两种引用类型,在实际应用中,引用里面需要变化Function的需求不多,最多要求调用一下。)

其实,解决办法说白了,就是重新拷贝一份新的数据,如果是基础类型的,直接赋值就OK, 引用类型的需要拷贝一份出来。这里的拷贝都要求能够深层拷贝对象。

方案1:递归法

function deepCopy(result, source) {
  for (var key in source) {
    var copy = source[key];
    if (source === copy) continue;//如window.window === window,会陷入死循环,需要处理一下
    if (is(copy, "Object")) {
      result[key] = arguments.callee(result[key] || {}, copy);
    } else if (is(copy, "Array")) {
      result[key] = arguments.callee(result[key] || [], copy);
    } else {
      result[key] = copy;
    }
  }
    
  return result;
  
  function is(obj, type) {
    var toString = Object.prototype.toString;
    return (type === "Null" && obj === null) ||
      (type === "Undefined" && obj === undefined ) ||
      toString.call(obj).slice(8, -1) === type;
  }

}
callee 的用法可以参见:JS 中的call,apply,bind 和 caller, callee

方案2:JSON序列化法

先把对象转成JSON格式的字符串,再将该字符串解析成新的对象。该方法可以一次性解决深层拷贝问题。简单易行。

var pa = {
  name: 'huasheng',
  age: '20',
  address: {
    province: 'zzz',
    city: 'aaa'
  }
};

var b = JSON.parse(JSON.stringify(pa));
console.log(b);
b.address.city = 'bbb';
console.log(b.address.city);    // bbb
console.log(pa.address.city);   // aaa

 

 

posted on 2013-09-15 14:34  花森  阅读(675)  评论(0编辑  收藏  举报