> 财经
javascipt深拷贝和浅拷贝的区别(js深拷贝和浅拷贝的使用场景)
导语:JavaScript中的深拷贝和浅拷贝
什么是深拷贝/浅拷贝浅拷贝是创建一个新对象,这个对象具有原始对象属性值。如果属性是基本类型的话,拷贝的就是基本类型。如果属性是引用类型,拷贝的就是引用地址,改变了其中一个对象,就会影响到另外一个对象。深拷贝是将一个对象从内存中完整拷贝了一份,从堆内存中开辟了一个新的区域存放新对象,修改后不会影响原来的对象。赋值、深拷贝、浅拷贝的区别对象数组赋值给一个新的变量时,其实是赋的内存地址,而不是对象中的数据。所以修改一个将影响另外一个。var person1 = { name: &39;, age: 20, list: [1, 2, 3]}let arr = [4,5,6]var person2 = person1;person2.age = 22;person2.list = arr;person2.list[0] = &39;;console.log(person1); // {name: &34;, age: 22, list:[&34;, 2, 3]}console.log(person2); // {name: &34;, age: 22, list:[&34;, 2, 3]}console.log(arr); // [&34;, 5, 6]
浅拷贝是重新在堆中创建内存,拷贝的基础类型互不影响,但是拷贝的引用类型共享同一个内存地址,会互相影响。var person = { name: &39;, age: 20, list: [1, 2, 3]}function shallowCopy(object) { let temp = {}; for (const key in object) { if (Object.hasOwnProperty.call(object, key)) { temp[key] = object[key]; } } return temp;}var shallowPerson = shallowCopy(person)console.log(shallowPerson); // {name: &34;, age: 20, list: [1, 2, 3]}shallowPerson.name = &39;;shallowPerson.list[0] = &39;;console.log(person); // {name: &34;, age: 20, list: [&39;, 2, 3]}console.log(shallowPerson); // {name: &34;, age: 20, list: [&39;, 2, 3]}
深拷贝是从堆内存中从新创建一个区域来存放新对象,并对对象中的子对象进行递归拷贝,互不影响。var person = { name: &39;, age: 20, list: [1, 2, 3]}function deepCopy(object){ let temp = Array.isArray(object) ? [] : {}; for (let key in object) { temp[key] = typeof object[key] === &39; ? deepCopy(object[key]) : object[key] } return temp;}var shallowPerson = deepCopy(person)console.log(shallowPerson); // {name: &34;, age: 20, list: [1, 2, 3]}shallowPerson.name = &39;; shallowPerson.list[0] = &39;; console.log(person); // {name: &34;, age: 20, list: [1, 2, 3]}console.log(shallowPerson); // {name: &34;, age: 20, list: [&39;, 2, 3]}
浅拷贝的实现方式ES6展开运算符 …
var person = { name: &39;, age: 20, list: [1, 2, 3], say:function(){console.log(&39;);}, check:new RegExp(&34;)}var user = { ...person}user.name = &39;console.log(user.name); // 李四console.log(person.name); // 张三
Object.assign()
var person = { name: &39;, age: 20, list: [1, 2, 3]}var user = Object.assign({},person)console.log(user); // // {name: &34;, age: 20, list: [1, 2, 3]}
lodash clone
var objects = [{ &39;: 1 }, { &39;: 2 }];var shallow = _.clone(objects);console.log(shallow[0] === objects[0]);// => true
Array concat
Array 的 concat方法不改变原数组,返回一个浅复制原数组的元素的新数组。如果元素是引用类型,就会拷贝这个引用的内存地址到新数组内。两个元素引用地址共享,所以如果发生改变将影响另外一个。如果元素是基本类型的话就会遵循浅拷贝的机制
var array = [1,[2,3,4],[5,6],{name:&39;}]let array_concat = array.concat()console.log(array_concat); // [1,2,3,[4,5,6],{name:&39;}]array_concat[1][0] = &39;console.log(array_concat[1]); // [&34;, 3, 4] console.log(array[1]); // [&34;, 3, 4]array_concat[2] = [&39;,&39;,&39;] // 这里之所以不一样,是因为改变了引用地址console.log(array_concat[2]); // [&34;, &34;, &34;]console.log(array[2]); // [5,6]array_concat[3].name = &39;;console.log(array_concat[3].name); // 王五console.log(array[3].name); // 王五
遍历复制
function shallowCopy(object) { let temp = {}; for (const key in object) { if (Object.hasOwnProperty.call(object, key)) { temp[key] = object[key]; } } return temp;}
深拷贝的实现方式JSON.parse/JSON.stringify
可以满足基本的使用,但是对于正则表达式类型、函数类型等无法进行深拷贝。
var person = { name: &39;, age: 20, list: [1, 2, 3], say:function(){console.log(&39;);}, check:new RegExp(&34;)}var user = JSON.parse(JSON.stringify(person));user.name = &39;;console.log(user.name); // 李四console.log(person.name); // 张三user.list[0] = &39;console.log(user.list); // [&34;, 2, 3]console.log(person.list); // [1, 2, 3]console.log(user.say); // undefinedconsole.log(user.check); // {}
lodash cloneDeep
var objects = [{ &39;: 1 }, { &39;: 2 }];var deep = _.cloneDeep(objects);console.log(deep[0] === objects[0]);// => false
递归遍历
var person = { name: &39;, age: 20, list: [1, 2, 3], say: function () { console.log(&39;); }, check: new RegExp(&34;)}function cloneDeep(object, hash = new WeakMap()) { if (!isObject(object)) return object; if(object instanceof Date) return new Date(object) if(object instanceof RegExp) return new RegExp(object) if (hash.has(object)) return hash.get(object) let target = Array.isArray(object) ? [] : {}; hash.set(object, target); for (const key in object) { if (Object.hasOwnProperty.call(object, key)) { if (typeof object[key] === &39;) { target[key] = cloneDeep(object[key], hash) } else { target[key] = object[key]; } } } return target;}function isObject(object) { return typeof object === &39; && object != null;}var user = cloneDeep(person);user.name = &39;;console.log(user.name); // 李四console.log(person.name); // 张三user.list[0] = &39; console.log(user.list); // [&34;, 2, 3]console.log(person.list); // [1, 2, 3]console.log(user.say); // undefinedconsole.log(user.check); // {}
本文内容由快快网络小樊整理编辑!