在ES6中新增了扩展运算符可以对数组和对象进行操作。有时候会遇到数组和对象的拷贝,可能会用到扩展运算符。那么这个扩展运算符到底是深拷贝还是浅拷贝呢?

一.、使用扩展运算符拷贝

  首先是下面的代码。

let a = [1,2,3];
let b = [...a];
a == b // false

  结果是false,这是很容易知道的,毕竟这个赋值操作符是由区别的。接下来将数组的只进行改变,又会怎样呢;

let a = [1,2,3];
let b = [...a];
a[0] = 11;
console.log(a); // [ 11, 2, 3 ]
console.log(b); // [ 1, 2, 3 ]

  发现a的值发生改变之后b的值并没有发生改变。所以就是深拷贝了吗?别急,接下来将数组中的元素设为引用类型。

let a = [1,2,[1,2,3]];
let b = [...a];
a[2][1] = 11;
console.log(a); // [ 1, 2, [ 1, 11, 3 ] ]
console.log(b); // [ 1, 2, [ 1, 11, 3 ] ]
console.log(a[2] === b[2]); // true
 

  这次的结果就有意思了,如果改变数组中的引用类型的元素中的值,此时a和b的值都会改变,并且a和b中的引用类型全等,也就是说地址是相同的。那么为什么是这样的呢?

二.、原因

  首先此分析仅为本人目前的认知。

  对于数组中的扩展运算符只是一个浅拷贝,仅对引用类型数据的第一层进行了拷贝,而倘若再深的层次就不会进行拷贝。

  另外对象的扩展运算符和数组是一样的。

let a = {
name : "Jyy",
msg : {
age : 29
}
}
let b = {...a};
console.log(a == b); // false
console.log(a.msg == b.msg); // true;
a.msg = {
age : "28"
}
console.log(a); // { name: 'Jyy', msg: { age: '28' } }
console.log(b); // { name: 'Jyy', msg: { age: 29 } }

三、深拷贝和浅拷贝的方法

  1.浅拷贝方法

    上面的例子已经看出来es6中的扩展运算符仅仅对引用类型进行了第一层的拷贝。除了es6的扩展运算符还有其他方法

    对象:

      使用Object.assign()

        Object.assign()用于对象的合并,如果第一个参数为{},则可对后面的对象参数进行拷贝

let a = {
name : "Jyy",
msg : {
age : 29
}
}
let b = Object.assign({},a);
console.log(a == b); // false
console.log(a.msg == b.msg); // true;
a.msg = {
age : "28"
}
console.log(a); // { name: 'Jyy', msg: { age: '28' } }
console.log(b); // { name: 'Jyy', msg: { age: 29 } }

    数组:

      数组的浅拷贝的方法很多

      a.使用slice()

        slice可以截取数组中部分的元素,若参数为空,则可对数组进行浅拷贝

let a = [1,2,[1,2,3]];
let b = a.slice();
console.log(a == b); // false
a[2][1] = 11;
a[0] = 11;
console.log(a); // [ 11, 2, [ 1, 11, 3 ] ]
console.log(b); // [ 1, 2, [ 1, 11, 3 ] ]
console.log(a[2] == b[2]); // true

      b.使用concat()

        concat可以对数组进行合并,若参数为空,亦可对数组进行浅拷贝

let a = [1,2,[1,2,3]];
let b = a.concat();
console.log(a == b); // false
a[2][1] = 11;
a[0] = 11;
console.log(a); // [ 11, 2, [ 1, 11, 3 ] ]
console.log(b); // [ 1, 2, [ 1, 11, 3 ] ]
console.log(a[2] == b[2]); // true

      c.使用Array.from()

let a = [1,2,[1,2,3]];
let b = Array.from(a);
console.log(a == b); // false
a[2][1] = 11;
a[0] = 11;
console.log(a); // [ 11, 2, [ 1, 11, 3 ] ]
console.log(b); // [ 1, 2, [ 1, 11, 3 ] ]
console.log(a[2] == b[2]); // true

  2.深拷贝

    对于深拷贝,数组和对象的方法是一致的

    a.递归方法,就是用for循环一层一层的进行拷贝,具体代码就不写了

    b.JSON.parse()

      这个方法通常用于调用接口传参或者是返回的字符串数据转成对象。

let a = {
name : "JYY",
age : "25",
msg : {
addr : "hebei"
}
}
b = JSON.parse(JSON.stringify(a));
console.log(a == b); // false
console.log(a.msg == b.msg); // false
a.msg.addr = "chengde";
console.log(a); // { name: 'JYY', age: '25', msg: { addr: 'chengde' } }
console.log(b); // { name: 'JYY', age: '25', msg: { addr: 'hebei' } }

      这个方法的弊端就是undefinedfunctionsymbol 会在转换过程中被忽略

let a = {
name : "JYY",
age : "25",
msg : {
addr : "hebei"
},
speek : function(){
console.log(this.name);
}
}
b = JSON.parse(JSON.stringify(a));
console.log(a); // { name: 'JYY', height: Symbol(jyy), age: undefined, msg: { addr: 'chengde' },speek: [Function: speek] }
console.log(b); // { name: 'JYY', msg: { addr: 'hebei' } }

    c.使用第三方插件

      比如lodash的深拷贝

const _ = require("lodash");
let syb = Symbol('jyy');
let a = {
name : "JYY",
height: syb,
age : undefined,
msg : {
addr : "hebei"
},
speek : function(){
console.log(this.name);
}
}
let b = _.cloneDeep(a);
console.log(a == b); // false
console.log(a.msg == b.msg); // false
console.log(a); // { name: 'JYY', height: Symbol(jyy), age: undefined, msg: { addr: 'chengde' },speek: [Function: speek] }
console.log(b); // { name: 'JYY', height: Symbol(jyy), age: undefined, msg: { addr: 'chengde' },speek: [Function: speek] }

ES6中数组和对象的扩展运算符拷贝问题以及常用的深浅拷贝方法的更多相关文章

  1. ES6 的Object.assign(target, source_1, ···)方法与对象的扩展运算符

    一.基本概念 Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target).它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象. Ob ...

  2. es6学习笔记--字符串&数值&数组&函数&对象的扩展

    这几天抽空学习了es6语法,关于字符串,数值,数组,函数以及对象的扩展,看到es6标准入门这本书,里面讲的扩展特别多,我认为有几部分在项目上用不到,就挑有用的当笔记学习了. 字符串的扩展 str.in ...

  3. ES6 数组、对象的扩展

    8. 数组的扩展 扩展运算符(...),将一个数组转为用逗号分隔的参数序列. 复制数组 const a2=[...a1] 合并数组 [...arr1, ...arr2, ...arr3]; arr1. ...

  4. ES6学习笔记(8)----对象的扩展

    参考书<ECMAScript 6入门>http://es6.ruanyifeng.com/ 对象的扩展 1.属性名的简洁表示法 : ES6允许在代码中直接写变量,变量名是属性名,变量值是属 ...

  5. ES6 学习笔记之四 对象的扩展

    ES6 为对象字面量添加了几个实用的功能,虽然这几个新功能基本上都是语法糖,但确实方便. 一.属性的简洁表示法 当定义一个对象时,允许直接写入一个变量,作为对象的属性,变量名就是属性名. 例1: , ...

  6. 小程序中监听textarea或者input输入的值动态改变data中数组的对象的值

    Page({ data: { todoLists:[ { detail:"", date:"", location:"", priority ...

  7. 小程序开发之改变data中数组或对象的某一属性值

    前言:在小程序的开发中,我们在view中便利data中数组或对象时,很多情况下需要在js中动态改变数组或者对象中某一香的属性值. 效果图: 我给大家总结了案例如下:   wxml如下: <scr ...

  8. ES6中数组的新方法

    数组的扩展 1.1扩展运算符 1.1.1:... 扩展运算符(spread)是三个点(...).它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列. <body> < ...

  9. ES6学习笔记(一)——扩展运算符和解构赋值

    前言 随着前端工程化的快速推进,在项目中使用ES6甚至更高的ES7等最近特性早已不是什么新鲜事.之前还觉得既然浏览器支持有限,那了解一下能看懂就好,然而仅仅了解还是不够的,现在放眼望去,那些成熟框架的 ...

随机推荐

  1. lua基础(2)

    错误处理: local function add(a,b) assert(type(a) == "number", "a 不是一个数字") assert(typ ...

  2. ARM系统时钟初始化

    2440时钟体系,12MHz的晶振 6410时钟体系,12MHz的晶振 210时钟体系,24MHz晶振 时钟初始化:1.设置locktime 2.设置分频系数 4.设置CPU到异步工作模式 3.设置f ...

  3. 三、Vue CLI-单页面

    一.单页面 代码如下: <template> <div class="header">{{title}}</div> </template ...

  4. java基本类型和包装类型的区别

    Java的类型分为两部分,一个是基本类型(primitive),如int.double等八种基本数据类型: 另一个是引用类型(reference type),如String.List等.而每一个基本类 ...

  5. centos7使用cron任务的相关命令(与centos6有区别)

    一.cron任务的自启动相关命令 1.检测cron定时服务是否自启用 systemctl is-enabled crond.service 结果展示如下: enable表示已启用自启动 disable ...

  6. 用Maven搭建简单的SpringMVC框架

    本文会详细阐述如何用Maven搭建一个简单的SpringMVC框架 这里就不介绍SpringMVC框架了,咱们直接来搭建 第一步 创建一个Maven的web项目  这里有一个简单的方法 new一个Ma ...

  7. Python核心技术与实战——十七|Python并发编程之Futures

    不论是哪一种语言,并发编程都是一项非常重要的技巧.比如我们上一章用的爬虫,就被广泛用在工业的各个领域.我们每天在各个网站.App上获取的新闻信息,很大一部分都是通过并发编程版本的爬虫获得的. 正确并合 ...

  8. 从输入一个URL到页面渲染的流程简介

    首先说明以下是我参考网上答案和自己的思考,给出自己的想法,如果有问题,欢迎大家吐槽从用户在浏览器中输入一个URL,到整个页面渲染,这个过程中究竟发生了什么呢?今天先简单写下整个过程,后面再一点点完善. ...

  9. webview默认是不开启localstorage的

    .setDomStorageEnabled(true);// 打开本地缓存提供JS调用,至关重要 转载 https://blog.csdn.net/xhf_123/article/details/77 ...

  10. 【Linux】CentOS6上mysql5.7安装

    1.下载安装yum源 根据系统下载yum源 https://dev.mysql.com/downloads/repo/yum/ rpm -ivh xxxxx.rpm 2.修改yum源 vim /etc ...