当前位置: 首页 > news >正文

JavaScript高级 —— 学习(四)

目录

一、深浅拷贝

(一)浅拷贝

1.浅拷贝的简单使用

拷贝对象:

拷贝数组:

使用两种浅拷贝方法

 2.浅拷贝的问题

(二)深拷贝

1.通过递归实现深拷贝

递归函数:

递归实现过程:

其他问题:

2.利用 lodash 实现深拷贝

3.利用 JSON 实现深拷贝 

练习:利用递归函数实现 setTimeout 模拟 setInterval 效果

未完待续。。。。


一、深浅拷贝

结构相同对象,复制对象重新赋值

不能用直接赋值来拷贝对象:o = obj

这样他俩指向同一个地址一个变了,就都变了

深浅拷贝只针对引用数据类型

(一)浅拷贝

适用于单层的对象和数组,不适用于多层嵌套的数组对象拷贝

最外层拷贝数值,内层拷贝地址

1.浅拷贝的简单使用
拷贝对象:

Object.assign() / 展开运算符 (...obj) 拷贝对象

拷贝数组:

Array.prototype.concat() / [...arr]

使用两种浅拷贝方法

解决了直接赋值的问题,这样就变成拷贝值(最外层)而不是地址

第一种:...展开运算符

<body><script>const obj = {uname: '一个人',age: 18}const o = { ...obj }console.log(o)o.age = 29console.log(o)console.log(obj)</script>
</body>

 第二种:Object.assign(被赋值的,赋值的)

<body><script>const obj = {uname: '一个人',age: 18}const o = {}Object.assign(o, obj)console.log(o)o.age = 29console.log(o)console.log(obj)</script>
</body>
 2.浅拷贝的问题

只拷贝最外层的值,如果有多层的话就变成拷贝地址了

如下只改变 拷贝出来的 o 对象的 family 的 num 属性,结果原本的 obj 中的 num 的值也变了,是因为有复杂多层对象时,里层拷贝的是地址,地址相同变一个都变了

<body><script>const obj = {uname: '一个人',age: 18,family: {num: 1}}const o = {}Object.assign(o, obj)console.log(o)o.family.num = 100console.log(o)console.log(obj)</script>
</body>

(二)深拷贝

直接拷贝对象,解决浅拷贝的问题,有三种方式实现深拷贝

1.通过递归实现深拷贝
递归函数:

函数内部调用自己就是递归函数

作用类似循环

容易发生栈溢出错误 必须添加退出条件

递归实现过程:

调用函数:直接看函数 deepCopy() 里卖两个实参 obj 和 o

函数内部:

for(k in oldobj) 循环递归 原本对象中的元素,因为是对象 k 代表的是对象中的属性名 而且 k 不是具体的属性名 不能用 oldobj.k 的形式 而应该用 [ ]

注意 oldobj[k] 和 newobj[k] 的含义不同 因为一个对象里面有东西,一个没东西 oldobj[k] 是指对象中具体的属性值 而 newobj[k] 指的是属性名

相当于 o.uname = obj.uname ('pink')

在外层时 直接进行赋值就行 newobj[k] = oldobj[k]

在内层时就得进行判断了,因为是数组也得进行递归赋值,所以直接用我们这个现成的函数递归实现就行

判断如果当前 oldobj[k] 属性值 是数组时 就再次调用函数,先初始化新数组 就是类似 上面的 o 得有个空的数组

当再次调用时oldobj[k] 变成了数组 ['足球', ‘篮球’] 此时 for(k in oldobj[k]) 递归中的 k 的意义变了,在数组中递归 k 是数组下标  然后分别遍历 足球 篮球 都不是数组 到 else 中进行赋值

就是newobj[0] = oldobj[0] ('足球')

newobj[1] = oldobj[1] ('篮球')

最后组成数组

递归实现完成

<body><script>const obj = {uname: 'pink',age: 18,hobby: ['足球', '篮球']}const o = {}function deepCopy(newobj, oldobj) {for (k in oldobj) {if (oldobj[k] instanceof Array) {newobj[k] = []deepCopy(newobj[k], oldobj[k])} else {newobj[k] = oldobj[k]}}}deepCopy(o, obj)o.hobby[0] = '羽毛球'console.log(o)console.log(obj)</script>
</body>
其他问题:

如果有内层还有对象的话

同理上面再加一个 else if 分支即可

但是注意!!!

Object 判断必须在 Array 下面因为数组也算对象 就会把 hobby 误认为是对象

<body><script>const obj = {uname: 'pink',age: 18,hobby: ['足球', '篮球'],family: {money: 100}}const o = {}function deepCopy(newobj, oldobj) {for (k in oldobj) {if (oldobj[k] instanceof Array) {newobj[k] = []deepCopy(newobj[k], oldobj[k])} else if (oldobj[k] instanceof Object) {newobj[k] = {}deepCopy(newobj[k], oldobj[k])} else {newobj[k] = oldobj[k]}}}deepCopy(o, obj)o.hobby[0] = '羽毛球'o.family.money = 20console.log(o)console.log(obj)</script>
</body>
2.利用 lodash 实现深拷贝

它是一个 js 库 里面有递归实现深拷贝的方法 可以直接下载进行调用

先引入再调用

_cloneDeep

<body><script src="./lodash.min.js"></script><script>const obj = {uname: 'pink',age: 18,hobby: ['足球', '篮球'],family: {money: 100}}const o = _.cloneDeep(obj)console.log(o)</script>
</body>
3.利用 JSON 实现深拷贝 

先把对象转换成字符串,然后再把字符串放到新的对象中转换回对象

<body><script>const obj = {uname: 'pink',age: 18,hobby: ['足球', '篮球'],family: {money: 100}}const o = JSON.parse(JSON.stringify(obj))console.log(o)</script>
</body>

练习:利用递归函数实现 setTimeout 模拟 setInterval 效果

界面展示:

代码部分:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div></div><script>function getTime() {document.querySelector('div').innerHTML = new Date().toLocaleString()setTimeout(getTime, 1000)}getTime()</script>
</body></html>

未完待续。。。。

相关文章:

  • 「MySQL」索引事务
  • electron打包桌面版.exe之vue项目踩坑(vue3+electron 解决打包后首页打开空白,打包后路由不跳转及请求不到后端数据等问题)
  • 基于OrangePi Zero2的智能家居项目(开发阶段)
  • EMD关于信号的重建,心率提取
  • Linux之进程间通信
  • 用JSch实现远程传输文件并打包成jar
  • (一)kafka实战——kafka源码编译启动
  • 睿尔曼超轻量仿人机械臂之复合机器人底盘介绍及接口调用
  • Linux|如何管理多个Git身份
  • 开源AI引擎:文本自动分类在公安及消防执法办案自动化中的应用
  • Serilog日志框架
  • Java- maven下载jar包,提示找不到,Could not find artifact
  • 机器学习-关联规则算法Apriori及编码实现
  • 【讲解下Gitea】
  • PyTorch 教程-快速上手指南
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • 4个实用的微服务测试策略
  • Apache Spark Streaming 使用实例
  • co模块的前端实现
  • Java 23种设计模式 之单例模式 7种实现方式
  • Java 最常见的 200+ 面试题:面试必备
  • JAVA_NIO系列——Channel和Buffer详解
  • MySQL用户中的%到底包不包括localhost?
  • Otto开发初探——微服务依赖管理新利器
  • python3 使用 asyncio 代替线程
  • select2 取值 遍历 设置默认值
  • Swift 中的尾递归和蹦床
  • Twitter赢在开放,三年创造奇迹
  • V4L2视频输入框架概述
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 前端路由实现-history
  • 让你的分享飞起来——极光推出社会化分享组件
  • 思维导图—你不知道的JavaScript中卷
  • 微信小程序开发问题汇总
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 由插件封装引出的一丢丢思考
  • 正则表达式-基础知识Review
  • 专访Pony.ai 楼天城:自动驾驶已经走过了“从0到1”,“规模”是行业的分水岭| 自动驾驶这十年 ...
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • ​TypeScript都不会用,也敢说会前端?
  • # 计算机视觉入门
  • #define
  • ${factoryList }后面有空格不影响
  • (pojstep1.3.1)1017(构造法模拟)
  • (二开)Flink 修改源码拓展 SQL 语法
  • (翻译)terry crowley: 写给程序员
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (转)c++ std::pair 与 std::make
  • (转载)Linux网络编程入门
  • (状压dp)uva 10817 Headmaster's Headache
  • ***详解账号泄露:全球约1亿用户已泄露
  • .a文件和.so文件