深拷贝和浅拷贝的方式,如何在JS中实现
说道数据拷贝就离不开数据类型,在js中数据类型分为基本类型和引用类型 基本类型:
number, boolean,string,symbol,bigint,undefined,null
引用类型:
object 以及一些标准内置对象 array、regexp、string、map、set..
一. 基本类型数据拷贝
基本类型数据都是值类型,存储在栈内存中,每次赋值都是一次复制的过程
var a = 12;
var b = a;
二. 引用类型数据拷贝
1、浅拷贝
只拷贝对象的一层数据,再深处层次的引用类型value将只会拷贝引用 实现方式:
1.object.assign() 和 es6的拓展运算符
通常我们用 object.assign() 方法来实现浅拷贝。 object.assign()用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。它将返回目标对象。
let aa = {
a: undefined,
func: function(){
console.log(1)}
,
b:2,
c: {
x: 'xxx', xx: undefined}
,
d: null,
e: bigint(100),
f: symbol('s')
}
let bb = object.assign({
}
, aa) // 或者 let bb = {
...aa}
aa.c.x = 111
console.log(bb)
// 第一层拷贝,遇到引用类型的值就会只拷贝引用
// {
// a: undefined,
// func: [function: func],
// b: 2,
// c: {
x: 111, xx: undefined }
,
// d: null,
// e: 100n,
// f: symbol(s)
// }
2.object.create
object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。object.create(proto,[propertiesobject])接收两个参数一个是新创建对象的__proto__, 一个属性列表
let aa = {
a: undefined,
func: function(){
console.log(1)}
,
b:2,
c: {
x: 'xxx', xx: undefined}
,
}
let bb = object.create(aa, object.getownpropertydescriptors(aa))
aa.c.x = 111
console.log(bb)
// 第一层拷贝,遇到引用类型的值就会只拷贝引用
// {
// a: undefined,
// func: [function: func],
// b: 2,
// c: {
x: 111, xx: undefined }
,
// }
2、深拷贝
在拷贝一个对象的时候为了避免修改对数据造成的影响,必须使用深拷贝。
实现方式:
1、 通过json.stringify()
var a = {
a:1, b: 2}
var b = json.stringify(a);
a.a = 'a'
console.log(a, b) // {
a: 'a', b: 2 }
{
"a":1,"b":2}
json.stringify()进行深拷贝有弊端: 忽略value为function, undefind, symbol, 并且在序列化bigint时会抛出语法错误:typeerror: do not know how to serialize a bigint
// 序列化function, undefind, symbol,忽略--------------------------------------------------------
var obj = {
a:function(){
}
,
b: undefined,
c: null,
d: symbol('s'),
}
var objcopyed = json.stringify(obj);
console.log("a:", a)
// obj: {
a: [function: a], b: undefined, c: null, d: symbol(s) }
console.log("objcopyed:", objcopyed)
// objcopyed: {
"c":null}
// 序列化bigint抛出错误--------------------------------------------------------
var obj = {
a: 1,
e: bigint(9007199254740991)
}
var objcopyed = json.stringify(obj);
// typeerror: do not know how to serialize a bigint
2、递归实现
const deepcopy = (obj) =>
{
// 优化 把值类型复制方放到这里可以少一次deepcopy调用
// if(!obj || typeof obj !== 'object') throw new error("请传入非空对象")
if(!obj || typeof obj !== 'object') return obj
let result = {
}
if (object.prototype.tostring.call(obj).indexof('array') >
0) {
result = []
}
// 另一种循环方式
// for (let key in obj) {
// if (obj.hasownproperty(key)) {
// result[key] = deepclone(obj[key])
// }
// }
object.keys(obj).foreach(key =>
{
// 优化 把值类型复制方放到这里可以少一次deepcopy调用
// if (obj[key] &
&
typeof obj[key] === 'object') {
// result[key] = deepcopy(obj[key])
// }
else{
// result[key] = obj[key]
// }
result[key] = deepcopy(obj[key])
}
);
return result
}
let aa = {
a: undefined,
func: function(){
console.log(1)}
,
b:2,
c: {
x: 'xxx', xx: undefined}
,
d: null,
e: bigint(100),
f: symbol('s')
}
let bb = deepcopy(aa)
aa.c.x = 123
aa.func = {
}
console.log("aa", aa)
console.log("bb", bb)
// aa {
// a: undefined,
// func: {
}
,
// b: 2,
// c: {
x: 123, xx: undefined }
,
// d: null,
// e: 100n,
// f: symbol(s)
// }
// bb {
// a: undefined,
// func: [function: func],
// b: 2,
// c: {
x: 'xxx', xx: undefined }
,
// d: null,
// e: 100n,
// f: symbol(s)
// }
手写深拷贝等这些工具方法,在实际生产中99.99%不会用到,毕竟有lodash、underscore这些方便的工具库呢
以上就是关于“深拷贝和浅拷贝的方式,如何在JS中实现”的相关知识,感谢各位的阅读,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注网络,小编每天都会为大家更新不同的知识。
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: 深拷贝和浅拷贝的方式,如何在JS中实现
本文地址: https://pptw.com/jishu/654502.html
