JavaScript的深克隆与浅克隆

JS数据类型分为两类: 基本类型(Number、Boolean、Undefined、Null、String、Symbol(ES6新加,此处不讨论))与引用类型(Object)。原始类型存储的是对象的实际数据,而对象类型存储的是对象的引用地址。

两种克隆

  1. 浅克隆: 原始类型为值传递,对象类型仍为引用传递。

  2. 深克隆: 所有元素或属性均完全复制,与原对象完全脱离,也就是说所有对于新对象的修改都不会反映到原对象中。

浅克隆

1.对于基本类型:

//数值克隆
var a="1";
var b=a;
b="2";
console.log(a);// "1"
console.log(b);// "2"

2.对于引用类型:

我们都知道,函数在js中属于“一等公民”,同时也是引用类型,但是函数的克隆是通过浅克隆就可以实现,因为函数的克隆会在内存单独开辟一块空间,互不影响

var m=function(){alert(1);};
var n=m;
n=function(){alert(2);};

console.log(m());//1
console.log(n());//2

下面通过一段代码来看浅克隆的问题:

function clone(obj){
var result={};
for(key in obj){
result[key]=obj[key];
}
return result;
}

var dog = {
name: '大黄',
age: 8,
hobby: {
food: 'cookie',
toy: 'ball'
}
}

var oNew = clone(dog);
console.log(dog.hobby.food); // cookie
oNew.hobby.food = "icecream";
console.log(dog.hobby.food) // icecream

简单的复制对象,如果对象其中一个属性是引用型变量,就会出现这种情况,因为引用型变量保存的是内存地址,所以其实后来操作的都是同一块内存。

深克隆

1.JSON对象的parse和stringify

JSON对象是ES5中引入的新的类型(支持的浏览器为IE8+),JSON对象parse方法可以将JSON字符串反序列化成JS对象,stringify方法可以将JS对象序列化成JSON字符串,借助这两个方法,也可以实现对象的深复制。

var dog = {
name: '大黄',
age: 8,
hobby: {
food: 'cookie',
toy: 'ball'
}
}

var oNew = JSON.parse(JSON.stringify(dog));
console.log(dog.hobby.food); // cookie
oNew.hobby.food = "icecream";
console.log(dog.hobby.food) // cookie

该方法的局限性:

  1. 无法复制函数

  2. 原型链没了,对象就是object,所属的类没了。

2.在jquery中extend方法可以用来扩展对象,这个方法可以传入一个参数:deep(true or false),表示是否执行深复制(如果是深复制则会执行递归复制),此处不细说。

3.自己定义

function deepClone(obj){
var result,
oClass=isClass(obj);

if(oClass="Object"){
result={};
}else if(oClass
="Array"){
result=[];
}else{
return obj;
}
for(key in obj){
var copy=obj[key];
if(isClass(copy)"Object"){
result[key]=arguments.callee(copy);//递归调用
}else if(isClass(copy)
"Array"){
result[key]=arguments.callee(copy);
}else{
result[key]=obj[key];
}
}
return result;
}
//返回传递给他的任意对象的类
function isClass(o){
if(o=null) return "Null";
if(o
=undefined) return "Undefined";
return Object.prototype.toString.call(o).slice(8,-1);
}

或者可以写为(只适用引用类型):

Object.prototype.clone = function(){

var o = this.constructor === Array ? [] : {};

for(var e in this){
o[e] = typeof this[e] === "object" ? this[e].clone() : this[e];
}
return o;
}

posted @ 2017-10-31 17:29  Lorin-Yang  阅读(234)  评论(2)    收藏  举报