js实现深拷贝
type函数
首先我们要实现一个getType函数对元素进行类型判断,关于元素的类型判断,可以参考我另一篇博文 js中typeof和instanceof详解 ,这里用一个更简便的方法,直接调用Object.prototype.toString
方法。
function getType(obj){
//tostring会返回对应不同的标签的构造函数
var toString = Object.prototype.toString;
var map = {
"[object Boolean]" : "boolean",
"[object Number]" : "number",
"[object String]" : "string",
"[object Function]" : "function",
"[object Array]" : "array",
"[object Date]" : "date",
"[object RegExp]" : "regExp",
"[object Undefined]": "undefined",
"[object Null]" : "null",
"[object Object]" : "object"
};
if(obj instanceof Element) {
return "element";
}
return map[toString.call(obj)];
}
深拷贝(deepClone)
对于一个引用类型,如果直接将它赋值给另一个变量,由于这两个引用指向同一个地址,这时改变其中任何一个引用,另一个都会受到影响。当我们想复制一个对象并且切断与这个对象的联系,就要使用深拷贝。对于一个对象来说,由于可能有多层结构,所以我们可以使用递归来解决这个问题
function deepClone(data){
var type = getType(data);
var obj;
if(type === "array"){
obj = [];
} else if(type === "object"){
obj = {};
} else {
//不再具有下一层次
return data;
}
if(type === "array"){
for(var i = 0, len = data.length; i < len; i++){
obj.push(deepClone(data[i]));
}
} else if(type === "object"){
for(var key in data){
obj[key] = deepClone(data[key]);
}
}
return obj;
}
对于function类型,这里是直接赋值的,还是共享一个内存值。这是因为函数更多的是完成某些功能,有个输入值和返回值,而且对于上层业务而言更多的是完成业务功能,并不需要真正将函数深拷贝。
广度优先遍历
上面是使用递归来进行深拷贝,显然我们可以使用树的广度优先遍历来实现
//这里为了阅读方便,只深拷贝对象,关于数组的判断参照上面的例子
function deepClone(data){
var obj = {};
var originQueue = [data];
var copyQueue = [obj];
//以下两个队列用来保存复制过程中访问过的对象,以此来避免对象环的问题(对象的某个属性值是对象本身)
var visitQueue = [];
var copyVisitQueue = [];
while(originQueue.length > 0){
var _data = originQueue.shift();
var _obj = copyQueue.shift();
visitQueue.push(_data);
copyVisitQueue.push(_obj);
for(var key in _data){
var _value = _data[key]
if(typeof _value !== "object"){
_obj[key] = _value;
} else {
//使用indexOf可以发现数组中是否存在相同的对象(实现indexOf的难点就在于对象比较)
var index = visitQueue.indexOf(_value);
if(index >= 0){
// 出现环的情况不需要再取出遍历
_obj[key] = copyVisitQueue[index];
} else {
originQueue.push(_value);
_obj[key] = {};
copyQueue.push(_obj[key]);
}
}
}
}
return obj;
}
JSON
深拷贝对象还有另一个解决方法,在对象中不含有函数的时候,使用JSON解析反解析就可以得到一个深拷贝对象
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: TP框架模型层简单的增删改查
- 下一篇: PHP中统计目录中文件以及目录中目录的大小