我对js数据类型的理解和深浅(copy)的应用场景
本人毕业一所专科院校,所学专业是计算机应用技术,在大学时对前端有了一定的了解之后,觉得自己对前端的兴趣十分强烈,开始自学前端,一路上也是坎坎坷坷,也有想要放弃的时候,还好坚持了下来,并且从事前端开发已将近三年,接下来就是谈谈我对深浅拷贝的理解和使用,望平台上的前辈给于关照和支持,若有不恰当之处请您及时指正。
一、js 数据类型
javaScritp的数据类型有:数值类型、字符串类型、布尔类型、null、undefined、对象(数组、正则表达式、日期、函数),大致分成两种:基本数据类型和引用数据类型。
(1)基本数据类型:数值、字符串、布尔、null、undefined (值类型)、symbol(ES6新增)
(2)复杂(复合)数据类型:对象 (引用类型);
基本数据类型保存在栈内存,引用类型保存在堆内存中。根本原因在于保存在栈内存的必须是大小固定的数据,引用类型的大小不固定,只能保存在堆内存中,但是可以把它的地址写在栈内存中以供我们访问
如果是基本数据类型,则按值访问,操作的就是变量保存的值;如果是引用类型的值,我们只是通过保存在变量中的引用类型的地址来操作实际对象。
1、复制基本类型数据
var a = 1;
var b = a;//复制
console.log(b)//1;
a = 2;//改变a的值
console.log(b)//1
赋值的时候,在栈内存中重新开辟内存,存放变量b,所以在栈内存中分别存放着变量a、b各自的值,修改时互不影响。
2、复制复杂类型的数据
var color1 = ['red','green'];
var color2 = color1;//复制
console.log(color2)//['red','green'];
color1.push('black') ;//改变color1的值
console.log(color2)//['red','green','black']
color1与color2指向堆内存中同一地址的同一对象,复制的只是引用地址
所以,对于引用类型的复制,简单赋值无用,需要拷贝。拷贝存在两种类型:深拷贝与浅拷贝
二、深浅拷贝的应用
浅拷贝的实现方式
(1) Object.assign()
可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。
(2) lodash的clone方法
(3)...操作符
let obj1 = { name: 'Kobei', address:{x:100,y:100}}
let obj2= {... obj1}
obj1.address.x = 200;
obj1.name = 'wade'
console.log('obj2',obj2) // obj2 { name: 'Kobe', address: { x: 200, y: 100 } }
复制代码(4) Array.prototype.concat
let arr = [1,2,3]; let arr2 = [4,5,6];let arr3 = arr.concat(arr2)
let arr = [1, 3, {
username: 'kobe'
}];
let arr2 = arr.concat();
arr2[2].username = 'wade';
console.log(arr);
复制代码(5) Array.prototype.slice
let arr = [1, 3, {2
username: ' kobe'
}];
let arr3 = arr.slice();
arr3[2].username = 'wade'
console.log(arr); // [ 1, 3, { username: 'wade' } ]
复制代码深拷贝的实现方式
(1) JSON.parse(JSON.stringify())
可以处理数组和对象的深拷贝,但是不能处理函数和正则,因为这两者基于这两个函数处理后得到的结果不再是正则/函数
缺点:
1. 会忽略undefined 2. 会忽略symbol
3. 不能序列化函数
4. 不能解决循环引用的对象
复制代码
(2) lodash的cloneDeep函数
(3) jQuery.extend函数
(4) 如果所拷贝的对象含有内置对象,但是不包含函数,可以使用messagechannel,可以拷贝undefined和循环引用的对象
```javascript
function structuralClone(obj) {
return new Promise(resolve => {
const { port1, port2 } = new MessageChannel()
port2.onmessage = ev => resolve(ev.data)
port1.postMessage(obj)
})
}
var obj = {
a: 1,
b: {
c: 2
}
}
obj.b.d = obj.b
// 注意该方法是异步的
// 可以处理 undefined 和循环引用对象
const test = async () => {
const clone = await structuralClone(obj)
console.log(clone)
}
test()
三、 手写浅拷贝:遍历=>直接等号赋值
// 浅拷贝
let obj1 = {
name : '深深地',
arr : [1,[2,3],4],
};
let obj3=shallowClone(obj1)
obj3.name = "春娇";
obj3.arr[1] = [5,6,7] ; // 新旧对象还是共享同一块内存
// 这是个浅拷贝的方法
function shallowClone(source) {
var target = {};
for(var i in source) {
if (source.hasOwnProperty(i)) {
target[i] = source[i];
}
}
return target;
}
console.log('obj1',obj1) // obj1 { name: '深深地', arr: [ 1, [ 5, 6, 7 ], 4 ] }
console.log('obj3',obj3) // obj3 { name: '春娇', arr: [ 1, [ 5, 6, 7 ], 4 ] }
obj.hasOwnProperty,返回值是一个布尔值,即是否是obj的属性(原型上的是false)
我对js数据类型的理解和深浅(copy)的应用场景的更多相关文章
- JS数据类型的理解(猜测)
Js 数据类型 对于这个主题,首先来看几个问题,如果你对这几个问题很清楚的话,那就请直接跳过吧,不用接着往下看了,如果不清楚,建议你还是看看. 1)如果判断函数?function 和object的联系 ...
- 基础数据类型的补充和深浅copy
一:关于str 的操作方法补充 1,s.isspace() 判断字符串是否只由空格组成,是,为True,否则,为False. s = ' ' #只能是以至少一个空格组成的字符串(全空格) prin ...
- day 07 数据类型,集合,深浅copy
1.day 06 内容回顾 小数据池 int :-5-256 str:特殊字符 ,*20 ascii:8位 1字节 表示一个字符 unicode:32位 4个字节 , 表示一个字符 字节表示8位表示一 ...
- python之路--基础数据类型的补充与深浅copy
一 . join的用法 lst =['吴彦祖','谢霆锋','刘德华'] s = '_'.join(lst) print(s) # 吴彦祖_谢霆锋_刘德华 # join() "*" ...
- python-基础数据类型,集合及深浅copy
一 数据类型定义及分类 我们人类可以很容易的分清数字与字符的区别,但是计算机并不能呀,计算机虽然很强大,但从某种角度上看又很傻,除非你明确的告诉它,1是数字,“汉”是文字,否则它是分不清1和‘汉’的区 ...
- Python基础学习Day7 基础数据类型的扩展 集合 深浅copy
一.基础数据类型的扩展 1.1GBK ---> UTF - 8 # str --->bytes s1 = '太白' # 字符串是unicode编码 b1 = s1.encode('gbk' ...
- python--基础数据类型的补充与深浅copy
一 . join的用法 lst =['吴彦祖','谢霆锋','刘德华'] s = '_'.join(lst) print(s) # 吴彦祖_谢霆锋_刘德华 # join() "*" ...
- 基础数据类型之集合和深浅copy,还有一些数据类型补充
集合 集合是无序的,不重复的数据集合,它里面的元素是可哈希的(不可变类型),但是集合本身是不可哈希(所以集合做不了字典的键)的.以下是集合最重要的两点: 去重,把一个列表变成集合,就自动去重了. 关系 ...
- 07、python的基础-->数据类型、集合、深浅copy
一.数据类型 1.列表 lis = [11, 22, 33, 44, 55] for i in range(len(lis)): print(i) # i = 0 i = 1 i = 2 del li ...
随机推荐
- gcc入门(下)
一 头文件与库文件(模块化,可重用,好维护)在使用C语言和其他语言进行程序设计的时候,我们需要头文件来提供对常数的定义和对系统以及库函数调用的声明库文件是一些预先编译好的函数的集合,那些函数都是按照可 ...
- 储存与RAID--独立磁盘阵列
存储: 专门用来插硬盘的机器,作用是增加插口,可以多插硬盘. 这种有策略保证硬盘坏了,数据不丢.而本地磁盘坏了,会导致数据丢失,故一般操作系统放在本地磁盘.而数据放在存储盘. 存储里依然有:cpu( ...
- ceph在centos7下一个不容易发现的改变
在centos6以及以前的osd版本,在启动osd的时候,回去根据ceph.conf的配置文件进行挂载osd,然后进行进程的启动,这个格式是这样的 [osd.0] host = hostname de ...
- Linux_Python版本控制
第1步:更新gcc,因为gcc版本太老会导致新版本python包编译不成功 复制代码代码如下: yum -y install gcc 系统会自动下载并安装或更新,等它自己结束 第2步:安装wget,这 ...
- inotify+rsync实时同步备份nfs
学习教程总结: 1.主机1:172.16.1.41,安装rsync并运行rsync --daemon 配置好/etc/rsyncd.conf 和密码文件rscync.password并设置chomd ...
- 死磕以太坊源码分析之Kademlia算法
死磕以太坊源码分析之Kademlia算法 KAD 算法概述 Kademlia是一种点对点分布式哈希表(DHT),它在容易出错的环境中也具有可证明的一致性和性能.使用一种基于异或指标的拓扑结构来路由查询 ...
- kali 系列学习07-攻击之密码生成
比较理想的字典是拖库字典,比如CSDN字典,如果要生成字典,可以使用Crunch 和 rtgen 两个工具, 一.密码生成 1.Crunch (1)启动crunch命令.执行命令如下所示. #crun ...
- Golang 实现 Redis(6): 实现 pipeline 模式的 redis 客户端
本文是使用 golang 实现 redis 系列的第六篇, 将介绍如何实现一个 Pipeline 模式的 Redis 客户端. 本文的完整代码在Github:Godis/redis/client 通常 ...
- [教程] Android Native内存泄漏检测方法
转载请注明出处:https://www.cnblogs.com/zzcperf/p/9563389.html Android 检测 C/C++内存泄漏的方法越来越简便了,下面列举一下不同场景下检测C/ ...
- Debian10快速部署DHCP服务
前言 DHCP(动态主机配置协议)是一个局域网的网络协议.指的是由服务器控制一段IP地址范围,客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码. 进日,想提升一下自己的技术水平,于是就做 ...