在JavaScript中,数据类型分为基本数据类型和引用数据类型。
基本数据类型是保存在栈内存中的,引用数据类型的变量是一个指向堆内存中实际对象的引用,这个引用是保存在栈内存中。
浅拷贝
浅拷贝,指的是创建新的数据。
如果原始数据的属性是基本类型,那拷贝的就是基本类型的值;如果原始数据的属性是引用类型,那拷贝的就是内存地址。浅拷贝是拷贝一层,引用类型部分共享内存地址。
实现一个浅拷贝功能的函数
javascript">function shallowClone(obj) {const newObj = {};for (const key in obj) {if (obj.hasOwnProperty(key)) {newObj[key] = obj[key]}}return newObj
}
在JavaScript中,提供一个浅拷贝的函数:
- Object.assign()
- 使用拓展运算符实现复制
- Array.prototype.slice()和Array.prototype.concat()
Object.assign
javascript">var obj = {age: 18,nature: ['smart', 'good'],names: {name1: '11',name2: '222'},love: function () {console.log('33333')}
}
var newObj = Object.assign({}, obj)
slice()
javascript">const fxArr = ["One", "Two", "Three"]
const fxArrs = fxArr.slice(0)
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]
concat()
javascript">const fxArr = ["One", "Two", "Three"]
const fxArrs = fxArr.concat()
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]
使用拓展运算符实现复制
javascript">const fxArr = ["One", "Two", "Three"]
const fxArrs = [...fxArr]
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]
深拷贝
深拷贝是开辟一个新的内存空间,两个对象属性完全相同,但是对应的两个不同地址。修改一个对象的属性,不会影响另一个对象。
常见的深拷贝函数:
- _.cloneDeep(),lodash库中的一个函数
- JSON.stringify()
- 手写循环递归
其中的JSON.stringify()会有一些弊端,它会忽略undefined 、Symbol和函数。
循环递归
javascript">function deepClone(obj, hash = new WeakMap()) {if (obj === null) return obj; // 如果是null或者undefined,就不进行遍历if (obj instanceof Date) return new Date(obj);if (obj instanceof RegExp) return new RegExp(obj);if (typeof obj !== "object") return obj;// 普通值或者函数,不需要遍历if (hash.get(obj)) return hash.get(obj);let cloneObj = new obj.constructor();hash.set(obj, cloneObj);for (let key in obj) {if (obj.hasOwnProperty(key)) {cloneObj[key] = deepClone(obj[key], hash);}}return cloneObj;
}