美文网首页
11_聊一聊js中实现数组拷贝的常用方法

11_聊一聊js中实现数组拷贝的常用方法

作者: 沐向 | 来源:发表于2020-04-09 21:19 被阅读0次

一、数组赋值

1、要点

用数组直接赋值的方式实现数组的拷贝,改变拷贝后的数组的元素,被拷贝的数组的元素也会发生改变

var arr1 = ["red","yellow","blue"];
var arr2 = arr1;
arr2[1] = "green";
console.log("数组的原始值:" + arr1 ); // 数组的原始值:red,green,blue
console.log("数组的新值:" + arr2);   // 数组的新值:red,green,blue

2、引用数据类型

Object 、Array 、Function

javascript的引用数据类型是保存在堆内存中的对象。

与其他语言的不同是,你不可以直接访问堆内存空间中的位置和操作堆内存空间。只能操作对象在栈内存中的引用地址。

所以,引用类型数据在栈内存中保存的实际上是对象在堆内存中的引用地址。通过这个引用地址可以快速查找到保存中堆内存中的对象。

var obj1 = new Object();
var obj2 = obj1;
obj2.name = "李雷";
console.log(obj1.name); // 李雷

[图片上传失败...(image-ce3171-1586438858767)]

二、数组浅拷贝

1、ES5 Array复制方法总结

(1)Array.slice(浅拷贝)

slice 方法根据我们指定的start、end的index从原数组中返回一个浅拷贝的数组。

 [1, 2, 3, 4, 5].slice(0, 3);
// [1, 2, 3]
// Starts at index 0, stops at index 3

测试:当不给定参数时,就返回了原数组的拷贝

let arr = [2, 4, 6, 8];
let arr1 = arr.slice();
console.log(arr1); // (4) [2, 4, 6, 8]
arr[0] = 'a';
console.log(arr, arr1); // (4) ["a", 4, 6, 8] (4) [2, 4, 6, 8]

(2)Array.cancat(浅拷贝)

concat将数组与值或其他数组进行组合。

[1, 2, 3].concat(4); // [1, 2, 3, 4]

测试:

let arr = ['a', 2, 4];
Array.prototype.clone = function () {
  return [].concat(this);
}
let arr1 = arr.clone();
console.log(arr1) // (3) ["a", 2, 4]

如果我们不指定参数或者提供一个空数组作为参数,就可以进行浅拷贝。

let arr = [1, 2, 3];
let arr1 = [1, 2, 3].concat();
let arr2 = [1, 2, 3].concat([]);
console.log(arr1, arr2); // (3) [1, 2, 3]  (3) [1, 2, 3] 

(3)遍历复制数组:for() 、while、map、 filter、 reduce

for()循环(浅拷贝)

测试1:

let arr = ['a', 2, 4];
 Array.prototype.clone = function () {
    let a = [];
    for (let i = 0, l = this.length; i<l; i++) {
        a.push(this[i]);
    }
    return a;
  }
let arr2 = arr.clone();
console.log(arr2) // (3) ["a", 2, 4]

测试2:

let numbers = [1, 2, 3];
let numbersCopy = [];
for (let i = 0; i < numbers.length; i++) {
 numbersCopy[i] = numbers[i];
}
console.log(numbersCopy) // (3) [1, 2, 3]

while()循环(浅拷贝)

let numbers = [1, 2, 3];
let numbersCopy = [];
let i = -1;
while (++i < numbers.length) {
 numbersCopy[i] = numbers[i];
}
console.log(numbersCopy) // (3) [1, 2, 3]

Array.map(浅拷贝)

当我们使用map方法时,需要给出一个callback函数用于处理当前的数组,并返回一个新的数组元素。

let numbers = [1, 2, 3];
let numbersCopy = numbers.map(x => x);
console.log(numbersCopy) // (3) [1, 2, 3]

Array.filter(浅拷贝)

Array.filter方法同样会返回一个新数组,但是并不一定是返回同样长度的,这和我们的过滤条件有关。

let numbers = [1, 2, 3];
let numbersCopy = numbers.filter(x => x);
console.log(numbersCopy) // (3) [1, 2, 3]

Array.reduce(浅拷贝)

其实用reduce来拷贝数组并没有展示出它的实际功能,但是我们还是要将其能够拷贝数组的能力说一下的。

let numbers = [1, 2, 3];
let numbersCopy = numbers.reduce((newArray, element) => {
 newArray.push(element);
 return newArray;
}, []);
console.log(numbersCopy) // (3) [1, 2, 3]

reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数,将其结果汇总为单个返回值。

2、ES6 方法总结

(1)Object.assign() 浅拷贝

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

let arr = ['张三', 24, '前端工程师', '男'];
let arr1 = [];
Object.assign(arr1, arr);
console.log(arr1); // (4) ["张三", 24, "前端工程师", "男"]

(2)扩展运算符(浅拷贝)

let arr = [1, 2, 3];
let arr1 = [...arr];
console.log(arr1) // (3) [1, 2, 3]

这个方法不能有效的拷贝多维数组。数组/对象值的拷贝是通过引用而不是值复制。

(3)Array.from(浅拷贝)

可以将任何可迭代对象转换为数组。给一个数组返回一个浅拷贝。

console.log(Array.from('foo')); // (3) ["f", "o", "o"]
let numbers = [1, 2, 3];
let numbersCopy = Array.from(numbers);
console.log(numbersCopy) // (3) [1, 2, 3]

三、数组深拷贝

JSON.parse & JSON.stringify(深拷贝)

  • JSON.stringify将一个对象转成字符串
  • JSON.parse将转成的字符串转回对象

将它们组合起来可以将对象转换成字符串,然后反转这个过程来创建一个全新的数据结构。

let nestedNumbers = [[1], [2]];
let numbersCopy = JSON.parse(
 JSON.stringify(nestedNumbers)
);
numbersCopy[0].push(300);
console.log(nestedNumbers, numbersCopy);
// [[1], [2]]
// [[1, 300], [2]]

这个可以安全地拷贝深度嵌套的对象/数组

几种特殊情况:

(1)如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式。而不是时间对象
let test = {
    name: 'a',
    date: [new Date(1536627600000), new Date(1540047600000)],
};
let b = JSON.parse(JSON.stringify(test));
console.log(b)
(2)如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象
const test = {
    name: 'a',
    date: new RegExp('\\w+'),
};
const copyed = JSON.parse(JSON.stringify(test));
test.name = 'test';
console.log(test, copyed)
(3)如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失
const test = {
    name: 'a',
    date: function help() {
        console.log('message')
    },
};
const copyed = JSON.parse(JSON.stringify(test));
test.name = 'test'
console.log(test, copyed)
11-4.png
(4)如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
(5)JSON.stringify()只能序列化对象的可枚举的自有属性

例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;

function Person(name) {
    this.name = name;
}
const lilei = new Person('lilei');
const test = {
    name: 'a',
    date: lilei,
};
const copyed = JSON.parse(JSON.stringify(test));
test.name = 'test'
console.log(test, copyed)

相关文章

  • 11_聊一聊js中实现数组拷贝的常用方法

    一、数组赋值 1、要点 用数组直接赋值的方式实现数组的拷贝,改变拷贝后的数组的元素,被拷贝的数组的元素也会发生改变...

  • Javascript中的深拷贝

    JS 中深拷贝的几种实现方法 1、使用递归的方式实现深拷贝 //使用递归的方式实现数组、对象的深拷贝 functi...

  • 重新认识js复杂类型数据的引用和深浅拷贝

    js 基本概念———— 数据类型 js 深浅拷贝之概念 代码实现 —— 数组和对象的j浅拷贝 代码实现 —— 数组...

  • JS 中深拷贝的几种实现方法

    JS 中深拷贝的几种实现方法 1、使用递归的方式实现深拷贝 方法二 2、通过 JSON 对象实现深拷贝 缺点 (1...

  • 前端笔记(6)JavaScript数组

    在最新的TypeScript 3.6中实现了更准确的数组扩展。借此机会聊一下我对js中数组的一点理解。 使用Arr...

  • javascript 数组以及对象的深拷贝

    数组的深拷贝在js中,数组和对象的复制如果使用=号来进行复制,那只是浅拷贝。如下图演示: for 循环实现数组的深...

  • JavaScript数组的拷贝

    JavaScript中数组的常用操作之数组的拷贝 展开操作符 拷贝数组的一种简单方法是使用展开运算符:const ...

  • 手写代码系列

    深拷贝 html转码 手写promise.all 有哪些实现数组扁平化的方法 原生js 运用flat方法 redu...

  • js 数组去重

    今天来聊一聊JS数组去重的一些方法,包括一些网上看到的和自己总结的,总共5种方法(ES5)。 第一种:遍历数组法 ...

  • 前端知识海底捞之JS

    AMD CMD CommonJS 阻止默认行为和阻止冒泡 JS数组 slice实现浅拷贝 concat实现浅拷贝 ...

网友评论

      本文标题:11_聊一聊js中实现数组拷贝的常用方法

      本文链接:https://www.haomeiwen.com/subject/ddehmhtx.html