js关于浅拷贝、深拷贝,数组的深拷贝

简介: 深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型。

🍀浅拷贝、深拷贝

深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型。
在这里插入图片描述
浅拷贝仅仅复制了指向某个对象的指针,并不复制对象本身,新对象与旧对象还是共享同一块内存,修改其中一个对象,另一个对象也会随之变化。
深拷贝会另外创造一个一模一样的对象,新对象跟旧对象不共享内存,修改其中一个对象不会影响到另一个对象。

在js当中,使用 ‘=’ 复制,就是js数组的浅拷贝。修改效果如下

var a=[1,0,0,8,6];
var b=a;
console.log(b);  //输出的是1,0,0,8,6
a[0]=5;
console.log(b);  //输出的是5,0,0,8,6

🍀实现数组的深拷贝

JSON.parse(JSON.stringify()) 方式

let arr = [5, 2, 9];
let arr2 = JSON.parse(JSON.stringify(arr));
arr2[2] = 0;
console.log(arr, arr2); // [5, 2, 9]  [5, 2, 0]

原理: 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,这样可以生成新的对象,新对象会开辟新内存栈,实现深拷贝。

这种方法虽然可以实现数组或对象深拷贝,但不能处理函数。

递归生成

   // 定义检测数据类型的功能函数
   function checkedType(target) {
     return Object.prototype.toString.call(target).slice(8, -1)
   }
   // 实现深度克隆---对象/数组
   function clone(target) {
     // 判断拷贝的数据类型
     // 初始化变量result 成为最终克隆的数据
     let result, targetType = checkedType(target)
     if (targetType === 'object') {
       result = {}
     } else if (targetType === 'Array') {
       result = []
     } else {
       return target
     }
     // 遍历目标数据
     for (let i in target) {
       // 获取遍历数据结构的每一项值。
       let value = target[i]
       // 判断目标结构里的每一值是否存在对象/数组
       if (checkedType(value) === 'Object' ||
         checkedType(value) === 'Array') { 
          // 对象/数组里嵌套了对象/数组
          // 继续遍历获取到value值
         result[i] = clone(value)
       } else { 
         // 获取到value值是基本的数据类型或者是函数。
         result[i] = value;
       }
     }
     return result
   }

concat 方法
concat() 方法用于连接两个或多个数组。
该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。

let arr = [5, 2, 9];
let arr2 = arr.concat();
arr2[2] = 0;
console.log(arr, arr2); // [5, 2, 9]  [5, 2, 0]

slice 方法

slice() 方法可从已有的数组中返回选定的元素。arrayObject.slice(start,end)方法返回一个新的数组,包含从 start 到 end (不包括该元素,数学上来讲是左闭右开,即包含左,不含右)的 arrayObject 中的元素。

let arr = [5, 2, 9];
let arr2 = arr.slice(0);
arr2[2] = 0;
console.log(arr, arr2); // [5, 2, 9]  [5, 2, 0]

ES6扩展运算符

...扩展运算符是ES6的语法。
但是需要注意的是:用扩展运算符对数组或者对象进行拷贝时,只能扩展和深拷贝第一层的值,对于第二层极其以后的值,扩展运算符将不能对其进行打散扩展,也不能对其进行深拷贝,即拷贝后和拷贝前第二层中的对象或者数组仍然引用的是同一个地址,其中一方改变,另一方也跟着改变。

let arr = [5, 2, 9,{
   name: ' kobe'
}];
let [...arr2] = arr;
arr2[2] = 0;
arr2[3].name = 'tom';
console.log(arr, arr2);

在这里插入图片描述

目录
相关文章
|
19天前
|
前端开发 JavaScript 开发者
【前端开发者的福音】彻底改变你编码习惯的神奇数组迭代技巧——从基础到进阶,解锁 JavaScript 数组迭代的N种姿势!
【8月更文挑战第23天】在Web前端开发中,数组是JavaScript中最常用的数据结构之一,掌握高效的数组迭代方法至关重要。本文详细介绍了多种数组迭代技巧:从基础的`for`循环到ES6的`for...of`循环,再到高阶方法如`forEach`、`map`、`filter`、`reduce`及`some`/`every`等。这些方法不仅能提高代码的可读性和维护性,还能有效优化程序性能。通过具体的示例代码,帮助开发者更好地理解和运用这些迭代技术。
24 0
|
8天前
|
JavaScript 前端开发
JavaScript基础知识-数组的遍历
关于JavaScript数组遍历基础知识的文章。
19 2
JavaScript基础知识-数组的遍历
|
8天前
|
JavaScript 前端开发
JavaScript基础知识-数组的练习
关于JavaScript基础知识中数组操作的练习,主要介绍了如何从一个包含Person对象的数组中过滤出成年人(年龄达到18岁及以上)并将他们放入一个新的数组中。
16 1
JavaScript基础知识-数组的练习
|
8天前
|
JavaScript 前端开发
JavaScript基础知识-数组的常用方法
关于JavaScript基础知识-数组的常用方法。
9 1
JavaScript基础知识-数组的常用方法
|
8天前
|
JavaScript 前端开发 索引
JavaScript基础知识-数组基于索引访问
关于JavaScript数组基于索引访问的基础知识介绍。
10 1
JavaScript基础知识-数组基于索引访问
|
8天前
|
JavaScript 前端开发
JavaScript基础知识-数组的定义方式
本文介绍了JavaScript中数组的多种定义方式。
9 1
JavaScript基础知识-数组的定义方式
|
4天前
|
存储 JavaScript 前端开发
JS中的数组有哪些常用操作函数和属性
【9月更文挑战第7天】JS中的数组有哪些常用操作函数和属性
8 1
|
13天前
|
JavaScript 前端开发 UED
JavaScript代码技巧大分享,在数组中去重元素
本文介绍了一系列实用的JavaScript函数,包括将内容复制到剪贴板、获取鼠标选中内容、打乱数组顺序、颜色值转换(RGBA与十六进制)、计算平均值、判断奇偶数、数组去重、检查空对象、反转字符串、计算日期间隔、首字母大写、生成随机字符串和随机数等,帮助提升网站的用户体验和功能丰富性。
19 4
|
14天前
|
JavaScript 前端开发 索引
JS中常用的数组迭代方法(filter,forEach,map,every,some,find,findIndex)
这段代码和说明介绍了JavaScript中数组的一些常用方法。函数接收三个参数:`item`(数组项的值)、`index`(项的位置,可选)和`array`(数组本身,可选)。示例展示了如何使用`filter()`过滤非空项、`forEach()`遍历数组、`map()`处理并返回新数组、`every()`检查所有元素是否满足条件、`some()`检查是否存在满足条件的元素、`find()`获取首个符合条件的元素值以及`findIndex()`获取其索引位置。这些方法都不会修改原数组。
JS中常用的数组迭代方法(filter,forEach,map,every,some,find,findIndex)
|
19天前
|
JavaScript
js如何判断数组内的值都为true
js如何判断数组内的值都为true
33 0