JavaScript深拷贝、浅拷贝
栏目: JavaScript · 发布时间: 5年前
内容简介:浅拷贝:浅拷贝只是复制了内存地址,如果原地址中的对象改变了,浅拷贝出来的对象也会相应改变。深拷贝:开辟了一块新的内存存放地址和地址指向的对象,原地址的任何对象改变了,深拷贝出来的对象不变。
JavaScript深拷贝、浅拷贝
浅拷贝:浅拷贝只是复制了内存地址,如果原地址中的对象改变了,浅拷贝出来的对象也会相应改变。
深拷贝:开辟了一块新的内存存放地址和地址指向的对象,原地址的任何对象改变了,深拷贝出来的对象不变。
浅拷贝数组(只拷贝第一级数组):
1.直接遍历
var arr = [1,2,3,4]; function copy(arg){ var newArr = []; for(var i = 0; i < arr.length; i++) { newArr.push(arr[i]); } return newArr; } var newArry = copy(arr); console.log(newArry); newArry[0] = 10; console.log(newArry); // [10,2,3,4] console.log(arr) // [1,2,3,4]
2.slice
var arr = [1,2,3,4] var copyArr = arr.slice(); copyArr[0] = 10; console.log(copyArr); // [10,2,3,4] console.log(arr); // [1,2,3,4]
slice(start,end) , slice()
方法返回一个数组中复制出来的元素组成新数组, start
指起始元素下标,end指终止元素下标
当 slice()
不带任何参数时,默认返回一个和原数组一样的新数组
3.concat()
var arr = [1,2,3,4] var copyArr = arr.concat(); copyArr[0] = 10; console.log(copyArr); // [10,2,3,4] console.log(arr); // [1,2,3,4]
array.concat(array1,array2,.......,arrayN) , concat()
方法用于连接两个或多个数组(不会改变原数组,返回被连接数组的副本)
然而如果第一级数组元素是对象或数组,上面三种方式都失效:
var arr = [ {number:1}, {number:2}, {number:3} ] var copyArr = arr.slice(); copyArr[0].number = 10; console.log(copyArr); // [{number: 100}, { number: 2 },{ number: 3 }] console.log(arr); // [{number: 100}, { number: 2 }, { number: 3 }]
浅拷贝对象(如果对象中的值不为数组或对象)
1.直接遍历
var obj = { name: "张三", job: "学生" } function copy (arg) { let newobj = {} for(let item in obj) { newobj[item] = obj; } return newobj; } var copyobj = copy(obj) copyobj.name = "李四" console.log(copyobj) // {name: '李四', job:: '学生'} console.log(obj) // {name: '张三', job:: '学生'}
2.ES6的Object.assign
var obj = { name: '张三', job: '学生' } var copyobj = Object.assign({},obj) copyobj.name = '李四' console.log(copyobj) // {name: '李四', job:: '学生'} console.log(obj) // {name: '张三', job:: '学生'}
Object.assign:用于对象的合并,将源对象 (source)
的所有可枚举属性,复制到目标对象 (target)
,并返回合并后的 target
用法: Object.assign(target, source1, source2) ; 所以 copyObj = Object.assign({}, obj) ; 这段代码将会把 obj
中的一级属性都拷贝到 {}
中,然后将其返回赋给 copyObj
3.ES6扩展运算符
var obj = { name: '张三', job: '学生' } var copyobj = {...obj} copyobj.name = '李四' console.log(copyobj) console.log(obj)
扩展运算符 (...)
用于取出参数对象的所有可遍历属性,拷贝到当前对象之中
深拷贝
JSON.stringify()
和 JSON.parse()
用 JSON.stringify
把对象转成字符串,再用 JSON.parse
把字符串转成新的对象。
但是这种方法也有不少坏处,譬如它会抛弃对象的 constructor
。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成 Object
。
这种方法能正确处理的对象只有 Number
, String
, Boolean
, Array
, 扁平对象,即那些能够被 json
直接表示的数据结构。 RegExp
对象是无法通过这种方式深拷贝。
也就是说,只有可以转成 JSON
格式的对象才可以这样用,像 function
、 undefined
、 symbol
、循环引用的对象没办法转成 JSON
。
var obj1 = { fun: function(){ console.log(123) } }; var obj2 = JSON.parse(JSON.stringify(obj1)); console.log(typeof obj1.fun); // 'function' console.log(typeof obj2.fun); // 'undefined' <-- 没复制
使用递归函数实现一个深拷贝的方法:
function deepClone(obj) { let objClone = Array.isArray(obj) ? [] : {}; if(obj && typeof obj === "object") { for(key in obj) { if(obj.hasOwnProperty(key)) { if(obj[key] && typeof obj[key] === "object") { objClone[key] = deepClone(obj[key]); } else { objClone[key] = obj[key]; } } } } return objClone }
以上所述就是小编给大家介绍的《JavaScript深拷贝、浅拷贝》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Head First HTML and CSS
Elisabeth Robson、Eric Freeman / O'Reilly Media / 2012-9-8 / USD 39.99
Tired of reading HTML books that only make sense after you're an expert? Then it's about time you picked up Head First HTML and really learned HTML. You want to learn HTML so you can finally create th......一起来看看 《Head First HTML and CSS》 这本书的介绍吧!