javascript 关于赋值、浅拷贝、深拷贝的个人理解


Posted in Javascript onNovember 01, 2019

一、栈、堆、指针地址

栈内存:个人理解是,基本数据类型和引用数据类型都会用到的一个空间,这个空间以key-value形式存在,value本身不可修改,只能赋值替换;

堆内存:堆,就是堆积,每一个被开辟的空间可以想象成一个空纸盒子,纸盒子所在的纸盒子堆就是 “堆” 。基本数据类型没有堆的概念。堆,只针对引用数据类型。存储方式应该是以对象(object)形式保存,对象内容包含key-value形式数据,value本身同样不可修改,只能赋值替换;

指针地址:针对引用数据类型在栈保存的值就是指针地址,地址指向保存在堆里面的对象。

二、赋值

赋值分两个,一个是基本数据类型的赋值,一个是引用数据类型的赋值,基本数据类型赋的是 “值”,引用数据类型赋的是 “指针地址”。

1.基本数据类型赋值

//在栈内开辟一个空间,空间名称叫a,存放值1;
var a = 1;

//在栈内开辟一个空间,空间名字叫b。接着先把a的值1复制一份,然后存放进b
var b = a;

如下图:

javascript 关于赋值、浅拷贝、深拷贝的个人理解

2.引用数据类型赋值

//首先在栈开辟一个空间a存放指针地址,设指针地址为address1;同时会在堆里面开辟一个空间放置对象数据 2 var a = {
 no: 1,
 per: {
  name: "jack"
 },
 per2: {
  name: "rose"
 }
}

//a赋值给b,此时b会在栈开辟一个空间b,用来放置address1,这个指针指向a所在堆的对象数据
var b = a;

//修改赋值后的值b,其实就是修改b的指针address1所指向的对象数据
b.no = 1314;

//修改b会影响原数据(所有层次的数据都会影响)
//这个原数据其实不是原数据,因为a和b其实都是同一个数据
//就像从中国去美国,可以从a地点(比如北京)或者b地点(比如上海)坐飞机去,但是到达的都是同一个地方(也就是对象数据)
b.per.name = "王五";

console.log(a, b)

上面代码打印如图:

javascript 关于赋值、浅拷贝、深拷贝的个人理解 

对b的修改会影响a原本的值。对a的修改同样会同步b的值,对a的修改本人没有写出,你们可以自己试试,结果是一样的。

针对上面的代码,引用数据类型赋值,如下图所示:

javascript 关于赋值、浅拷贝、深拷贝的个人理解

无论修改a对象还是b对象,都是在修改 “obj” 这个对象

三、浅拷贝

引用数据类型的浅拷贝,代码如下:

//在栈开辟一个空间a,存放a的指针地址,设指针地址为address2a,同时在堆开辟一个空间,设这空间为A,存放a对象数据
var a = {
 no: 1,
 per: {
  name: "jack",
 },
 per2: {
  name: "rose"
 }
}

//在栈开辟一个空间b,存放b的指针地址,设指针地址为address2b,同时在堆开辟一个空间,设这空间为B,存放b对象数据
var b = {};

//对a的数据进行循环,判断如果有key,就把值赋到B对应的key位置
//这个循环,遇到数据类型为基本数据类型,赋的是值;遇到引用数据类型,赋的是指针地址
for(var p in a) {
 if(a.hasOwnProperty(p)) {
  b[p] = a[p]
 }
}

//对b的第一层修改
b.no = 1314;
b.per2 = [];

//对b的第二层修改
b.per.name = "王五";

//浅拷贝,修改b后,第一层修改都不影响原数据,第二层以及以上层次的修改都影响原数据
//当前没有写第三层及以上层次,可自行测试。
console.log(a, b)

运行结果如图:

javascript 关于赋值、浅拷贝、深拷贝的个人理解

可以理解为,a原本的东西被完全复制了一份,放到了b里面,然会对b的操作,就只关b的事情了。a原本是什么值,现在依然是什么值,b的修改对a完全没有影响。

最后,可用下图表示深拷贝:

javascript 关于赋值、浅拷贝、深拷贝的个人理解

四、深拷贝

深拷贝,说白了,就是对浅拷贝的递归,也就是浅拷贝章节所述的,浅拷贝第一层已经被完全拷贝到新的地方,然后第二层以及以上层次,它们的属性值又将都会被拷贝到新的地方,最后就井水不犯河水了。

代码如下:

//在栈开辟一个空间a,存放a的指针地址,设指针地址为address3a,同时在堆开辟一个空间,设这空间为space1a,存放a对象数据
var a = {
 no: 2,
 per: {
  name: "jack"
 },
 per2: {
  name: "rose"
 }
}

//用递归的方式对a进行拷贝属性和值,然后赋值给temp,然后return出去。此时不拷贝指针地址。
function getDeep(obj) {
 var temp = Array.isArray(obj) ? [] : {};
 for(var p in obj) {
  if(typeof obj[p] == "object") {
   temp[p] = getDeep(obj[p])
  } else {
   temp[p] = obj[p]
  }
 }
 return temp;
}

//在栈开辟一个空间b,存放b的指针地址,设指针地址为address3b。同时b在堆开辟一个空间,设这空间为D,存放temp的对象数据
var b = getDeep(a);

//深拷贝后,修改b的值,不论修改属性值,还是整个值替换都不影响原数据a
b.no = 1314;
b.per = []
b.per2 = {
 name:"王五"
}

console.log(a, b)

浅拷贝只拷贝了第一层,深拷贝是拷贝到最后一层。代码运行结果如图:

javascript 关于赋值、浅拷贝、深拷贝的个人理解

可以理解为,a原本的东西被完全复制了一份,放到了b里面,然会对b的操作,就只关b的事情了。a原本是什么值,现在依然是什么值,b的修改对a完全没有影响。

最后,可用下图表示深拷贝:

javascript 关于赋值、浅拷贝、深拷贝的个人理解

五、总结

1.赋值:

基本数据类型就是类似a同学有一台电脑,b同学也想要,就也给b同学买了一台一模一样的电脑b,电脑a和电脑b各自怎么被操作都是a同学和b同学各自的事,电脑显示互不影响(数据结果);

引用数据类型就是只有一台电脑,放在了电脑室,a同学和b同学各自从宿舍到电脑室操作电脑,都能影响电脑显示;在a同学和b同学的眼里,最后结果这台电脑显示什么,取决于最后一个操作电脑的同学(数据结果);

2.浅拷贝:

a同学有一台笔记本电脑并且配置了全套装备,触感舒爽的鼠标、按键响亮的机械键盘等。b同学没钱买电脑,但是又很想体验,所以先买了和a同学一样的鼠标键盘自个先看着爽。然后向a同学借电脑过来玩。a同学和b同学各自的鼠标键盘出了啥问题,两个人之间互不影响对方的使用。而对电脑的操作就是谁最后操作了电脑,电脑就是显示最后那个人的操作界面(数据修改)。

3.深拷贝:

a同学有笔记本+全套装备,b同学羡慕不已,自己让a同学照着买了一整套一模一样的给自己,但是他们各自的使用电脑情况,取决于他们各自的操作,电脑之间互不影响(数据结果)。

以上纯属个人理解,有误勿喷请指出,谢谢!

Javascript 相关文章推荐
javascript vvorld 在线加密破解方法
Nov 13 Javascript
jQuery移动和复制dom节点实用DOM操作案例
Dec 17 Javascript
Angularjs 基础入门
Dec 26 Javascript
jquery判断输入密码两次是否相等
Apr 22 Javascript
AngularJS 整理一些优化的小技巧
Aug 18 Javascript
浅谈jquery高级方法描述与应用
Oct 04 Javascript
JS鼠标滚动分页效果示例
Jul 05 Javascript
jQuery实现checkbox的简单操作
Nov 18 jQuery
浅谈Vue下使用百度地图的简易方法
Mar 23 Javascript
es6新特性之 class 基本用法解析
May 05 Javascript
详解JavaScript中的强制类型转换
Apr 15 Javascript
仿照Element-ui实现一个简易的$message方法
Sep 14 Javascript
vue iview的菜单组件Mune 点击不高亮的解决方案
Nov 01 #Javascript
解决vue项目刷新后,导航菜单高亮显示的位置不对问题
Nov 01 #Javascript
vue实现点击追加选中样式效果
Nov 01 #Javascript
vue 导航内容设置选中状态样式的例子
Nov 01 #Javascript
解决vue-router 二级导航默认选中某一选项的问题
Nov 01 #Javascript
微信js-sdk 录音功能的示例代码
Nov 01 #Javascript
使用 Angular RouteReuseStrategy 缓存(路由)组件的实例代码
Nov 01 #Javascript
You might like
php中将汉字转换成拼音的函数代码
2012/09/08 PHP
php实现微信公众平台账号自定义菜单类
2014/12/02 PHP
PHP实现的猴王算法(猴子选大王)示例
2018/04/30 PHP
thinkphp 框架数据库切换实现方法分析
2020/05/18 PHP
修改发贴的编辑功能
2007/03/07 Javascript
跟着JQuery API学Jquery 之二 属性
2010/04/09 Javascript
jquery插件制作 自增长输入框实现代码
2012/08/17 jQuery
js中判断Object、Array、Function等引用类型对象是否相等
2012/08/29 Javascript
jQuery打印指定区域Html页面并自动分页
2014/07/04 Javascript
JavaScript中的Math.sin()方法使用详解
2015/06/15 Javascript
JS模拟键盘打字效果的方法
2015/08/05 Javascript
跟我学习javascript的执行上下文
2015/11/18 Javascript
原生javascript实现匀速运动动画效果
2016/02/26 Javascript
JS Ajax请求如何防止重复提交
2016/06/13 Javascript
jquery实现楼层滚动效果
2018/01/01 jQuery
vue+element 模态框表格形式的可编辑表单实现
2019/06/07 Javascript
使用JavaScript获取扫码枪扫描得到的条形码的思路代码详解
2020/06/10 Javascript
netbeans7安装python插件的方法图解
2013/12/24 Python
Python的面向对象思想分析
2015/01/14 Python
Python中用PIL库批量给图片加上序号的教程
2015/05/06 Python
使用python调用zxing库生成二维码图片详解
2017/01/10 Python
关于Python如何避免循环导入问题详解
2017/09/14 Python
Python遍历pandas数据方法总结
2018/02/09 Python
python 使用elasticsearch 实现翻页的三种方式
2020/07/31 Python
小米官方旗舰店:Xiaomi
2020/08/07 全球购物
体育学院毕业生自荐信
2013/11/03 职场文书
汽车装潢店创业计划书范文
2014/02/05 职场文书
物流专员岗位职责
2014/02/17 职场文书
司仪主持词两篇
2014/03/22 职场文书
社会体育专业大学生职业生涯规划书
2014/09/17 职场文书
个人存款证明书
2014/10/18 职场文书
保研专家推荐信范文
2015/03/25 职场文书
廉洁自律承诺书范文
2015/04/28 职场文书
南京南京观后感
2015/06/02 职场文书
九九重阳节致辞
2015/07/31 职场文书
《弟子规》读后感:知廉耻、明是非、懂荣辱、辨善恶
2019/12/03 职场文书