js数组和对象深拷贝
在JS中,一般的 = 号传递的都是对象/数组的引用,并没有真正地拷贝一个对象,那如何进行对象的深度拷贝呢?
对象的深拷贝
通常情况下,我们可以使用最简单,最直接的方法,JSON.parse()与JSON.stringfy()实现对象的深克隆,代码如下:
const clone = function(obj) {
return JSON.parse(JSON.stringfy(obj));
}
但需要注意和记住的是,这种方法只适合纯数据JSON对象的深度克隆,不过也都可以满足我们日常情况下的开发,对于复杂结构的深拷贝,大家可以参考一下方法:
const clone = function (obj) {
if(obj === null) return null
if(typeof obj !== 'object') return obj;
if(obj.constructor===Date) return new Date(obj);
if(obj.constructor === RegExp) return new RegExp(obj);
var newObj = new obj.constructor (); //保持继承链
for (var key in obj) {
if (obj.hasOwnProperty(key)) { //不遍历其原型链上的属性
var val = obj[key];
newObj[key] = typeof val === 'object' ? arguments.callee(val) : val; // 使用arguments.callee解除与函数名的耦合
}
}
return newObj;
};
补充方法 ES6扩展运算符实现对象的深拷贝
let aa={a:1,b:undefined,c:function(){},d:new Date()}
aa //{a: 1, b: undefined, c: ƒ, d: Tue Apr 23 2019 13:22:56 GMT+0800 (中国标准时间)}a: 1b: undefinedc: ƒ ()d: Tue Apr 23 2019 13:22:56 GMT+0800 (中国标准时间) {}__proto__: Object
let bb={...aa}
bb //{a: 1, b: undefined, c: ƒ, d: Tue Apr 23 2019 13:22:56 GMT+0800 (中国标准时间)}a: 1b: undefinedc: ƒ ()d: Tue Apr 23 2019 13:22:56 GMT+0800 (中国标准时间) {}__proto__: Object
aa.e=null
aa //{a: 1, b: undefined, c: ƒ, d: Tue Apr 23 2019 13:22:56 GMT+0800 (中国标准时间), e: null}
bb //{a: 1, b: undefined, c: ƒ, d: Tue Apr 23 2019 13:22:56 GMT+0800 (中国标准时间)}
数组深拷贝
数组的深拷贝,方法有很多
1、遍历
let arr = ["a", "b"], arrCopy = [];
for (var item in arr) arrCopy[item] = arr[item];
arrCopy[1] = "c";
arr // => ["a", "b"]
arrCopy // => ["a", "c"]
多重数组则写成方法,递归自己即可。
2、slice()
定义和用法slice()
方法可从已有的数组中返回选定的元素。
语法arrayObject.slice(start,end)
参数 描述
start 必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。
end 可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。
返回值
返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject
中的元素。
let arrCopy = arr.slice(0);
arrCopy[1] = "c";
arr // => ["a", "b"]
arrCopy // => ["a", "c"]
3、concat()
定义和用法
concat() 方法用于连接两个或多个数组。
该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。
语法 arrayObject.concat(arrayX,arrayX,......,arrayX)
参数 描述
arrayX 必需。该参数可以是具体的值,也可以是数组对象。可以是任意多个。
返回值
返回一个新的数组。该数组是通过把所有 arrayX 参数添加到 arrayObject
中生成的。如果要进行 concat() 操作的参数是数组,那么添加的是数组中的元素,而不是数组。
let arrCopy = arr.concat();
arrCopy[1] = "c";
arr // => ["a", "b"]
arrCopy // => ["a", "c"]
4、JSON.parse()与 JSON.stringify()
(1)JSON.parse函数
作用:将json字符串转换成json对象。
语法:JSON. parse(text[,reviver]).
参数:text 必须;一个有效的json字符串。
reviver 可选。
返回值:一个对象或数组。
(2)JSON.stringify()函数
作用:将json对象转换成json字符串。
语法:JSON.stringify(value [, replacer] [, space])
参数:value 必须;通常为对象或数组。
replacer 可选,用于转换结果的函数或者数组。
space 可选。向返回值 JSON 文本添加缩进、空格和换行符以使其更易于读取。
返回值:一个包含JSON文本的字符串。
let arrCopy = JSON.parse(JSON.stringify(arr));
arrCopy[1] = "c";
arr // => ["a", "b"]
arrCopy // => ["a", "c"]
5、ES6扩展运算符实现数组的深拷贝
… 扩展运算符是ES6的语法,使用起来非常的方便简洁,相信在写ES6的时候也是备受欢迎的。
let arrCopy = [...arr];
arrCopy[1] = "c";
arr // => ["a", "b"]
arrCopy // => ["a", "c"]
习大大
哈哈
嘻嘻?
恢复
你好