ES6对象展开运算符浅拷贝or深拷贝

news/2024/7/11 0:55:44 标签: es6, 前端, javascript

ES6中提出的对象展开运算符“…”就是用来展开元素的。有了它就不用代码循环遍历了,偷懒专用。

1. 合并数组

展开原有数组中的所有元素,可以合并成一个新的数组。

javascript">var a=[1,2,3];
var b=[4,5,6];
var c=[...a,...b];
console.log(c) // 输出:[1, 2, 3, 4, 5, 6]
console.log(a) // 输出:[1, 2, 3]
console.log(b) // 输出:[4, 5, 6]

2. 合并对象

展开对象中的所有属性,可以合并成一个新的对象。

javascript">var person = {
  name: '小明',
  age: 18,
  sex: '男',
};
var hobby = {
  play: '篮球',
  like: '吃饭、睡觉、打游戏',
};
var xiaoMing = {...person,...hobby};
console.log(xiaoMing); // { name: '小明', age: 18, sex: '男', play: '篮球', like: '吃饭、睡觉、打游戏' }

当对象中包含同名参数时,后面的会把前面的同名属性覆盖掉。

javascript">// 接上面的代码
var xiaoGang = {
    ...person,
    ...hobby,
    ...{name:'小刚',play:'足球'},
};
console.log(xiaoGang); // { name: '小刚', age: 18, sex: '男', play: '足球', like: '吃饭、睡觉、打游戏' }

3. 对象展开运算符是浅拷贝还是深拷贝?

先来了解下,浅拷贝和深拷贝各自的含义。

数据可以分为两大类:一类是基本数据,一类是引用数据;而数据存储位置又可分为栈和堆。

基本数据:存储在栈中,

引用数据:栈中存储了一个地址,这个地址指向堆中的真实数据。

由此:

浅拷贝:在栈中新开辟了一个空间,复制的是栈中的地址,改地址指向的依旧是原来堆的数据。

深拷贝:在栈和堆中均重新开辟了空间,新的地址指向的是新的数据,老地址指向的是老数据,所以无论新旧数据哪个发生变化,都不会影响另一个。

下面看一个浅拷贝的例子:

javascript">var person = {
  name: '小明',
  age: 18,
  sex: '男',
}

var xiaoHong = person; // 这里只是将引用变量person1给了xiaoHong
xiaoHong.name = '小红';

console.log(person) // 输出:{name: "小红", age: 18, sex: "男"}
console.log(xiaoHong)// 输出:{name: "小红", age: 18, sex: "男"}

由上面的例子,很清楚的看到:当xiaoHong的name属性值变化了之后,person的name属性值也发生变化了,所以两个对象指向的是同一个数据区域,是浅拷贝。

那么对象展开运算符是浅拷贝还是深拷贝呢?看下面例子:

javascript">var person = {
  name: '小明',
  age: 18,
  sex: '男',
}

var xiaoHong = {...person}
xiaoHong.name = '小红';

console.log(person) // 输出: {name: "小明", age: 18, sex: "男"}
console.log(xiaoHong)// 输出: {name: "小红", age: 18, sex: "男"}

诶?用对象展开符的xiaoHong的name属性变化了之后,person的name属性没有变化呀!难道对象扩展符是深拷贝?别急,往下看。

再看下面的例子,对象中包含着第二层数据对象。

javascript">var person = {
  name: '小明',
  age: 18,
  sex: '男',
  hobby: {
    play: '篮球',
    like: '吃饭、睡觉、打游戏',
  }
}

var xiaoHong = {...person}
xiaoHong.name = '小红';
xiaoHong.hobby.play = '羽毛球';

console.log(person);   // 输出: {name: "小明", age: 18, sex: "男", hobby: {music: "羽毛球",like: "吃饭、睡觉、打游戏"}}
console.log(xiaoHong); // 输出: {name: "小红", age: 18, sex: "男", hobby: {music: "羽毛球",like: "吃饭、睡觉、打游戏"}}

对比新旧两个对象的输出:

      针对name属性: 旧对象没受到影响;针对hobby.play属性:旧对象跟随变化了。

由此可证明对象展开运算符并不是深拷贝,也是浅拷贝,但第一层又不是浅拷贝。

我感觉可以这么理解:

对象展开预算符相当于展开遍历了对象的第一层数据,第一层数据如果是基本数据,就是简单的值;第一层数据若是引用数据,就是浅拷贝。


http://www.niftyadmin.cn/n/61037.html

相关文章

Monaco Editor教程(二二):monaco编辑器完整配置翻译及重点配置解析

前言 本篇文章讲解一下创建Monaco编辑器时所有完整配置,算是一个比较浅显的入门文章。 但由于一个Monaco的配置项多达150个,整篇文章耗费了我5天的下班时间,请读者自行点赞收藏。这里结合实际的项目业务场景介绍一些常用的,有可能修改的默认配置参数。Monaco已经默认了很多…

关于安卓10以上连接wifi无法联网的问题

连接方式 在Android10之前应用内连接wifi是调用addNetwork和enableNetwork。但在Android10以后以上方法不会生效。 在Android10及以上,官方提供了以下应用内连接wifi的方式:文档 val specifier WifiNetworkSpecifier.Builder().setSsidPattern(Patte…

猴子吃桃-递归Java

题目: 一只小猴买了若干个桃子。第一天他刚好吃了这些桃子的一半,又贪嘴多吃了一个;接下来的每一天它都会吃剩余的桃子的一半外加一个。第 (n(n≤20)) 天早上起来一看,只剩下 (1) 个桃子了。请问小猴买了几个桃子? 输…

【macOS】mac电脑M2芯片安装Homebrew 最简单的方法

一 Homebrew的安装 打开终端,复制如下命令,按回车执行 M芯片和Intel芯片均可 中途可能需要你手动输入密码,输入完成回车即可(密码不可见 选择中科大或者清华镜像源 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/Hom…

活动回顾|深入了解Accelerator Program孵化计划

本期Twitter Space由Moonbeam官方和Moonbeam Accelerator孵化计划背后的运营Rokk3r联合直播,为社区深入了解Accelerator Program孵化计划。 收听直播回放:https://twitter.com/MoonbeamNetwork/status/1616118120737013761 直接申请Moonbeam Accelerat…

高级前端二面vue面试题(持续更新中)

action 与 mutation 的区别 mutation 是同步更新, $watch 严格模式下会报错 action 是异步操作,可以获取数据后调用 mutation 提交最终数据 MVVM的优缺点? 优点: 分离视图(View)和模型(Model)&#xff…

别具一格,原创唯美浪漫情人节表白专辑,(复制就可用)(html5,css3,svg)表白爱心代码(1)

别具一格,原创唯美浪漫情人节表白专辑, (复制就可用)(html5,css3,svg)表白爱心代码(1) 一、 前言 回眸之间,丰盈了岁月,涟漪了思绪,轻轻落笔,不写伤痕,不写仇怨,只写岁月…

Zookeeper实现分布式锁

文章目录ZK节点类型watch监听机制Zookeeper实现分布式锁锁原理创建锁的过程释放锁的过程ZK锁的种类代码实现Zookeeper是一个开源的分布式协调服务,是一个典型的分布式数据一致性解决方案。 分布式应用程序可以基于Zookeeper实现诸如数据发布/订阅,负载均…