# 浅拷贝与深拷贝
4 min read
Table of Contents
JavaScript 变量有两种不同数据类型:基本类型和引用类型。
基本数据类型是按值访问,可以直接操作保存在变量中的实际值。引用类型的值是保存在堆内存中的对象,JavaScript 不能直接操作对象的内存空间,实际操作的是对象的引用。在传递的时候,基本类型是传值,引用类型是传址。所以,浅拷贝与深拷贝只针对于引用类型这种对象。
浅拷贝与深拷贝
浅拷贝:浅拷贝只拷贝对象的引用地址,并没有创建新的对象,并没有开辟新的堆内存。拷贝出来的变量是同一个引用地址,指向同一个对象。
深拷贝:深拷贝是对引用的对象全部进行拷贝。在内存中创建了新的对象,拷贝出来的变量指向不同的引用地址,指向不同的对象。
浅拷贝的示例
- 赋值操作
var arr = [1, 2, 3, 4]var obj = { a: 'a', b: 'b' }var arrCopy = arrvar objCopy = obj
arrCopy[0] = 0objCopy.a = 'aa'
log(arr, arrCopy) //[0, 2, 3, 4], [0, 2, 3, 4]log(obj, objCopy) //{ a: "aa", b: "b" }, { a: "aa", b: "b" }特别的浅拷贝
当数据只有一层的时候,该方法可以当作深拷贝使用。当数据超过一层时候,只能用作浅拷贝。
- Array.slice() —常用作数组
var arr = [1, 2, 3, 4]var arrCopy = arr.slice()arrCopy.push(5)log(arr, arrCopy)//[1, 2, 3, 4], [1, 2, 3, 4, 5]var arr = [1, 2, 3, 4, [10, 11]]var arrCopy = arr.slice()arrCopy[4].push(12)log(arr, arrCopy)//[1, 2, 3, 4, [10, 11, 12]], [1, 2, 3, 4, [10, 11, 12]]- Ojbect.assign() —常用作对象
var obj = { a: 'a', b: 'b' }var objCopy = Object.assign({}, obj)objCopy.a = 'aaa'log(obj, objCopy)//{ a: "a", b: "b" }, { a: "aaa", b: "b" }var obj = { a: 'a', b: 'b', c: { d: 'd' } }var objCopy = Object.assign({}, obj)objCopy.c.d = 'ddd'log(obj, objCopy)//{ a: 'a', b: 'b', c: {d: "ddd"} }, { a: 'a', b: 'b', c: {d: "ddd"} }- 扩展运算符… —数组,对象都常用
var arr = [1, 2, 3, 4]var obj = { a: 'a', b: 'b' }var arrCopy = [...arr]var objCopy = { ...obj }arr.push(5)obj.c = 'c'log(arr, arrCopy) //[1, 2, 3, 4, 5] [1, 2, 3, 4]log(obj, objCopy) //{ a: "a", b: "b" }, { a: "a", b: "b", c: "c" }深拷贝
- JSON.parse 和 JSON.stringify
var obj = { a: { b: 'c' } }var objCopy = JSON.parse(JSON.stringify(obj))objCopy.a.b = 'd'log(obj, objCopy) //{ a: { b: "c"} }, { a: { b: "d"} }局限性:无法转换function,function会直接消失掉。
var obj = { fun: function () { console.log('hi') },}var objCopy = JSON.parse(JSON.stringify(obj))log(typeof obj.fun) //"function"log(typeof objCopy.fun) //"undefined"-
Jquery 的 extend
-
Lodash 的 cloneDeep
题外话
数组的部分方法原本是不改变原数组的,如 map, filter, find…等等。但是如果数组项是对象的话,且遍历时修改原数组项会修改原数组。
const arr = [1, 2, 3]const arr2 = [{ value: 1 }, { value: 2 }]
const copy = arr.map((i) => { i += 1 return i})const copy2 = arr2.map((i) => { i.value += 1 return i})
console.log(arr, copy)// [1, 2, 3] [2, 3, 4]console.log(arr2, copy2)// [{ value: 2 }, { value: 3 }] [{ value: 2 }, { value: 3 }]