js css htmlJavaScript理论知识

11-02:实现 JS 中所有对象的深度克隆(包装对象,Date

2022-05-16  本文已影响0人  小小前端搬运工

通过递归可以简单实现对象的深度克隆,但是这种方法不管是 ES6 还是 ES5 实现,都有同样的缺陷,就是只能实现特定的 object 的深度复制(比如数组和函数),不能实现包装对象 Number,String , Boolean,以及 Date 对象,RegExp 对象的复制。

(1)前文的方法

function deepClone(obj){ 

var newObj= obj instanceof Array?[]:{}; 

for(var i in obj){ 

newObj[i]=typeof obj[i]=='object'? 

deepClone(obj[i]):obj[i]; 

}

return newObj; 

}

这种方法可以实现一般对象和数组对象的克隆,比如:

var arr=[1,2,3]; 

var newArr=deepClone(arr); 

// newArr->[1,2,3] 

var obj={ 

x:1, 

y:2 

}

var newObj=deepClone(obj); 

// newObj={x:1,y:2} 

但是不能实现例如包装对象 Number,String,Boolean,以及正则对象 RegExp 和 Date 对象的克隆,比如:

//Number 包装对象 

var num=new Number(1); 

typeof num // "object" 

var newNum=deepClone(num); 

//newNum -> {} 空对象 

//String 包装对象 

var str=new String("hello"); 

typeof str //"object" 

var newStr=deepClone(str); 

//newStr-> {0:'h',1:'e',2:'l',3:'l',4:'o'}; 

//Boolean 包装对象

var bol=new Boolean(true); 

typeof bol //"object" 

var newBol=deepClone(bol); 

// newBol ->{} 空对象

....

(2)valueof()函数

所有对象都有 valueOf 方法,valueOf 方法对于:如果存在任意原始值,它就默认将对象转换为表示它的原始值。对象是复合值,而且大多数对象无法真正表示为一个原始值, 因此默认的 valueOf()方法简单地返回对象本身,而不是返回一个原始值。数组、函数和正则表达式简单地继承了这个默认方法,调用这些类型的实例的 valueOf()方法只是简单返回这个对象本身。

对于原始值或者包装类:

function baseClone(base){ 

return base.valueOf(); 

}

//Number 

var num=new Number(1); 

var newNum=baseClone(num); 

//newNum->1 

//String 

var str=new String('hello'); 

var newStr=baseClone(str); 

// newStr->"hello" 

//Boolean 

var bol=new Boolean(true); 

var newBol=baseClone(bol); 

//newBol-> true 

其实对于包装类,完全可以用=号来进行克隆,其实没有深度克隆一说,这里用 valueOf 实现,语法上比较符合规范。

对于 Date 类型:

因为 valueOf 方法,日期类定义的 valueOf()方法会返回它的一个内部表示:1970 年 1 月 1 日以来的毫秒数.因此我们可以在 Date 的原型上定义克隆的方法:

Date.prototype.clone=function(){ 

return new Date(this.valueOf()); 

}

var date=new Date('2010'); 

var newDate=date.clone(); 

// newDate-> Fri Jan 01 2010 08:00:00 GMT+0800 

对于正则对象 RegExp:

RegExp.prototype.clone = function() { 

var pattern = this.valueOf(); 

var flags = ''; 

flags += pattern.global ? 'g' : '';

flags += pattern.ignoreCase ? 'i' : ''; 

flags += pattern.multiline ? 'm' : ''; 

return new RegExp(pattern.source, flags); 

};

var reg=new RegExp('/111/'); 

var newReg=reg.clone(); 

//newReg-> /\/111\//
上一篇下一篇

猜你喜欢

热点阅读