JavaScript中的对象复制

news/2024/7/19 16:39:14 标签: js

所有的面向对象的语言中,都存在着对象引用、复制等等问题,对于初学者来说可能难以理解。今天我来总结一下JavaScript中对象复制。

首先我们要知道JavaScript中的数据分为基本类型(单类型)引用类型。除了Object对象,其余都是基本类型例如我们常见的String、Number、boolean、null、undefined。而数组、时间对象以及我们自定义的对象等等,都是继承自Object的,所以说都是引用类型。

js中对对象进行赋值时,基本类型会被直接复制,例如下:

let a = 1;
let b = a;
b = 2;
console.log(a);
console.log(b);

效果:

可见a,b都是number基本类型,直接赋值就把a复制给了b,改变b并不改变a。

同样可以看这个:

function ch(num) {
	num = num + 10;
}

let a = 1;
console.log(a);
ch(a);
console.log(a);

结果:

我们试图通过函数改变a的值,但是没有成功。因为把a作为形参传入后,形参会作为传入实参的一个副本,相当于先做了mun = a的操作,再num自己加10,函数结束,num被销毁,num是a的复制品,num变了也不影响a。

下面建立一个对象,对其进行操作试试看:

//构造角色技能对象
let gzskill = {
	skillName: '把你变成布丁',
	description: '对敌人造成伤害并回复自身生命值',
	injury: 2000
}

//构造一个角色对象
let miyako = {
	name: '宫子',
	age: '14',
	race: 'ghost',
	skill: gzskill,
	say: () => {
		console.log('我~好~恨~啊~');
	}
}
let miyakoCopy = miyako;
miyakoCopy.name = '出云宫子';
console.log(miyako);
console.log(miyakoCopy);

这里我建立了个自定义对象miyako,然后新建变量miyakoCopy,改变新建变量,原变量会变吗?结果如下:

可见虽然只改变了新对象,但是原对象也被改了,这是为什么呢?

因为我们自定义的对象属于Object类型,属于引用类型直接赋值给别的对象时,只是发生了引用,相当于miyako和miyakoCopy两个名字指向了内存中同一空间如果改变其中一个,另一个也会发生变化

这在js中属于浅复制,即我们把已有对象赋值给新对象时并没有给新对象在内存中开辟一个新空间,而是发生引用。

同样把对象作为形参传入函数,你会发现它也发生了改变:

//构造角色技能对象
let gzskill = {
	skillName: '把你变成布丁',
	description: '对敌人造成伤害并回复自身生命值',
	injury: 2000
}

//构造一个角色对象
let miyako = {
	name: '宫子',
	age: '14',
	race: 'ghost',
	skill: gzskill,
	say: () => {
		console.log('我~好~恨~啊~');
	}
}

function chName(char) {
	char.name = '出云宫子';
}
console.log(miyako);
chName(miyako);
console.log(miyako);

结果:

可以理解为,对象作为形参传入后,函数内会先创建副本对象并将传入实参直接赋值给副本,然后再对副本进行操作。而我们传入的是引用类型的数据,因此建立的副本对象也只是对传入实参进行了浅复制。

那么我们想要复制一个对象,即实现深复制,怎么做呢?

可以写一个函数,新建一个对象,并通过遍历、递归方式对原对象的属性进行获取,把每个属性依次给新对象复制。如果属性是基本类型数据例如数值字符串等等,我们就可以直接赋值给新对象属性了,因为基本类型直接赋值就是相当于真正的复制了,如果是引用类型那就进行递归操作:

/**
 * 对对象进行深复制
 * @param {*} originObject 原对象
 * @returns 复制的对象
 */
function copyObject(originObject) {
	let destObject = {};
	for (let key in originObject) {
		let property = originObject[key];
		if (property == null) {
			destObject[key] = null;
		} else if (property == undefined) {
			destObject[key] = undefined;
		} else if (typeof property == 'object') {
			destObject[key] = copyObject(property);
		} else {
			destObject[key] = property;
		}
	}
	return destObject;
}

然后我们对上面已经构造的对象进行试验:

let miyakoCopy = copyObject(miyako);
miyakoCopy.name = '出云宫子';
miyakoCopy.skill.injury = 3000;
miyakoCopy.say = () => {
	console.log('不给布丁就捣蛋!');
}
console.log(miyako);
miyako.say();
console.log(miyakoCopy);
miyakoCopy.say();

结果:

可见通过该方法实现了深复制,无论是对象本身还是对象里面的对象都实现了深复制。

其实在Java、C#等等面向对象的编程语言中,对象的复制、引用都是和上述js中的情况是一样的。


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

相关文章

正则不能全为某个值_深度学习模型中的正则化实例

深度学习模型具有很大的灵活性,如果机器学习训练数据集不够大,过度拟合可能成为一个严重的问题。让我们来看一个例子。问题陈述你刚刚被法国足球公司聘为人工智能专家。他们希望您推荐法国守门员应将足球踢到的位置,以便法国队的球员可以用头…

业务功能“二级分销”简单实现

1.什么是二级分销? 二级分销其实是一种让用户分裂通过邀请的形式来获得更多的用户。如有ABC三个人,A邀请B做一件事情,B邀请C做一件事情。假定通过直接邀请可获得10%利润,通过间接邀请可获得5%的利润,设这件事定价为100…

php小白到大牛的集训营_一文带你学习从Python小白到大牛的代码成长之路(初级篇)...

收藏!长文!从Python小白到大牛,要走的路这里都有面向项目的学习是学习编码的最佳方法。Python是当今最需求的语言,为了帮助您学习它,以下是一些您可以探索的最重要的Python项目:Python游戏Python图像编程CI…

[WM]在WM上面使用WS貌似有性能问题(欢迎讨论)

很想在WM程序中使用WS,但是一直没有实践.今天写了一个小Demo,看看WS的性能怎么样,Server不是我写的,我用的是别人公开的Server:1. 随机数http://www.webxml.com.cn/WebServices/RandomFontsWebService.asmx2. 天气http://www.webxml.com.cn/WebServices/WeatherWebService.asmx…

python交互式命令_python实现定制交互式命令行的方法

Python的交互式命令行可通过启动文件来配置。 当Python启动时,会查找环境变量PYTHONSTARTUP,并且执行该变量中所指定文件里的程序代码。该指定文件名称以及地址可以是随意的。按Tab键时会自动补全内容和命令历史。这对命令行的有效增强,而这些工具则是基…

MySQL实现排名

排名在我们日常生活中并不陌生,例如玩游戏的分数等等排名,都需要用到SQL语句查询数据库。不过具体怎么通过SQL语句实现排名呢? 为了举例说明,我先随便定义一个表和一些数据,以便于下面的查询: create tab…

蓝桥杯java 算法提高 扶老奶奶过街

一共有5个红领巾,编号分别为A、B、C、D、E,老奶奶被他们其中一个扶过了马路。  五个红领巾各自说话:  A :我和E都没有扶老奶奶  B :老奶奶是被C和E其中一个扶过大街的  C :老奶奶是被我和D其中一个…

python 实数如何取整_视频教程-Python新手入门篇-汇总目录

如果你是python新手,还没有安装python环境,请你先看这里的视频python教程:视频教程-Python环境准备篇-汇总目录​zhuanlan.zhihu.compython教程:python入门课-2 python代码是什么样子的python教程:命令行cmd、PowerShe…