第一次在掘金写笔记,若有错误,还请指出哈!写的不好的地方,还请多多包涵!
js分基本数据类型和引用数据类型。
基本数据类型:Number
String
Boolean
Symbol
undefined
null
,存储在堆
当中,动态分配的内存,大小不定也不会自动释放。
引用数据类型:object
,栈
中存储地址,自动分配内存空间。地址(0xffff)
-> 堆中的内容
。
浅拷贝:对于 基本数据类型
来说,修改拷贝前后互不影响;对于 引用数据类型
来说,修改拷贝前后第一层互不影响,但是 修改深层次内容会有影响,因为拷贝前后的变量指向的是同一块内存空间。
深拷贝:针对引用数据类型
多层而言,深拷贝
相当于在内存空间内重新开辟了新的空间存储值
,所以修改拷贝前后的变量不会互相影响。
常见的浅拷贝
方法:
Object.assign()
- 展开运算符(...)
- 自己通过js实现
常见的深拷贝
方法:
递归
遍历,一个值一个值的拷贝(本文主要介绍递归方式的实现)JSON.stringfy()
&JSON.parse()
,function 和 undefined 不可用lodash
- JQuery的
$.extend([deep], target, object1 [, objectN ])
方法,通过第一个参数为true
或者false
来指定深浅拷贝
好了,下面咱们进入正题:
/**
* 判断变量的类型
* @param {object} value 变量值
*/
function checkType(value) {
return Object.prototype.toString.call(value).slice(8, -1);
}
/**
* 深拷贝(递归)
* @param {*} sourceValue 需要拷贝的值
*/
function deepClone(sourceValue) {
// 如果传入的数据是简单类型(不是 {} & []),直接返回即可
if (typeof sourceValue !== "object") {
return sourceValue;
}
// 判断 传入参数的数据类型(object or array)
let targetType = checkType(sourceValue);
// 根据传入参数的数据类型,创建 初始存储结果的变量类型 {} or []
let result = targetType === "Object" ? {} : [];
// 遍历 sourceValue (for...in可以遍历数据和对象)
// 避免数组内有自定义属性,遍历数组使用 for...of,遍历对象 for...in
if (targetType === "Array") {
// 传入参数是数组时,次数使用的是 for...of 遍历,当然,也可以使用 数组的其他遍历方法
for (const [key, value] of sourceValue.entries()) {
let itemType = checkType(item);
// 如果 value 是 数组 或 对象,则继续遍历
if (itemType === "Object" || itemType === "Array") {
result[key] = deepClone(value);
} else {
// 如果 value 是 基本数据类型 或者 函数,直接赋值即可
result[key] = value;
}
}
} else {
// 传入参数是对象时
for (const key in sourceValue) {
// 遍历数组时,key 为数组的 下标
// 遍历对象时,key 为对象的 key
// hasOwnProperty 只能检验对象自身的属性,不能检验继承属性,也不能检验原型链上的属性
if (sourceValue.hasOwnProperty(key)) {
const item = sourceValue[key];
let itemType = checkType(item);
// 如果 value 是 数组 或 对象,则继续遍历
if (itemType === "Object" || itemType === "Array") {
result[key] = deepClone(item);
} else {
// 如果 value 是 基本数据类型 或者 函数,直接赋值即可
result[key] = item;
}
}
}
}
// 返回 result 即可
return result;
}
嗯嗯,第一次分享就到这儿啦!!!
虽然知识简单而且少的可怜!!!