js深拷贝和浅拷贝
本章节介绍一下浅拷贝和深拷贝。
之所以出现深拷贝,也是由于要规避浅拷贝的缺陷,先来看一个浅拷贝的代码:
var original = { age: 3, webName: "前端教程网", antzoneObj: { address: "青岛市南区", target:"分享互助" } }; var extend = function (result, source) { for (var key in source) { result[key] = source[key]; } return result; } var newObj = extend({}, original); newObj.antzoneObj.address = "青岛市北区"; console.log(newObj.antzoneObj.address); console.log(original.antzoneObj.address);
从上面的代码可以看出,虽然我只想修改新对象的属性,但是原来对象的属性也被改变了。
因为result[key] = source[key]传递的知识对象的存储地址,{address: "青岛市南区",target:"分享互助"}没有真正被拷贝。
下面就来看一下深度拷贝:
var original = { age: 3, webName: "前端教程网", antzoneObj: { address: "青岛市南区", target:"分享互助" } }; dom = {}; dom.is = function (obj, type) { var toString = Object.prototype.toString, undefined; return (type === "Null" && obj === null) || (type === "Undefined" && obj === undefined) || toString.call(obj).slice(8, -1) === type; }; dom.deepCopy = function (result, source) { for (var key in source) { var copy = source[key]; if (result === copy) continue; if (dom.is(copy, "Object")) { result[key] = arguments.callee(result[key] || {}, copy); } else if (dom.is(copy, "Array")) { result[key] = arguments.callee(result[key] || [], copy); } else { result[key] = copy; } } return result; }; var newObj = dom.deepCopy({}, original); newObj.antzoneObj.address = "青岛市北区"; console.log(newObj.antzoneObj.address); console.log(original.antzoneObj.address);
上面的代码实现深度拷贝效果,下面介绍一下它的实现过程。
一.代码注释:
(1).var original = {
age: 3,
webName: "前端教程网",
antzoneObj: {
address: "青岛市南区",
target:"分享互助"
}
},创建一个待拷贝的对象,内部嵌套有一个对象。
(2).dom = {},声明一个空对象,其实用作一个命名空间功能。
(3).dom.is = function (obj, type) {
var toString = Object.prototype.toString, undefined;
return (type === "Null" && obj === null) ||
(type === "Undefined" && obj === undefined) ||
toString.call(obj).slice(8, -1) === type;
},此方法的功能是准确判断数据的类型,第一个参数要判断的数据,第二个参数是类型,返回值是一个布尔值。
dom.deepCopy = function (result, source) {},实现深度拷贝功能,第一个参数目标对象,第二个参数是要被拷贝的对象。
(4).for (var key in source) {},遍历对象中的每一个属性。
(5).var copy = source[key],获取对应的属性值。
(6).if (result === copy) continue,防止是同一个对象产生死循环。
(7).if (dom.is(copy, "Object")) {
result[key] = arguments.callee(result[key] || {}, copy);
},判断是否是一个对象。然后用递归的方式进行拷贝操作。
result[key] || {}的作用是,如果目标对象中没有同名属性,那么就使用一个空对象。
二.相关阅读:
(1).prototype可以参阅javascript prototype原型一章节。
(2).call()可以参阅js call()一章节。
(3).slice()可以参阅javascript slice()一章节。