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 相关文章推荐
js no-repeat写法 背景不重复
Mar 18 Javascript
JavaScript 获取当前时间戳的代码
Aug 05 Javascript
IE6下js通过css隐藏select的一个bug
Aug 16 Javascript
js不能跳转到上一页面的问题解决方法
Mar 01 Javascript
yepnope.js使用详解及示例分享
Jun 23 Javascript
javascript每日必学之运算符
Feb 16 Javascript
javascript 使用正则test( )第一次是 true,第二次是false
Feb 22 Javascript
微信小程序网络请求的封装与填坑之路
Apr 01 Javascript
JavaScript控制浏览器全屏显示简单示例
Jul 05 Javascript
微信小程序的注册页面包含倒计时验证码、获取用户信息
May 22 Javascript
微信小程序实用代码段(收藏版)
Dec 17 Javascript
在react中使用vue的状态管理的方法示例
May 02 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访问查询mysql数据的三种方法
2006/10/09 PHP
php 修改zen-cart下单和付款流程以防止漏单
2010/03/08 PHP
Windows下Apache + PHP SESSION丢失的解决过程全纪录
2015/04/07 PHP
PHP程序员不应该忽略的3点
2015/10/09 PHP
mysql desc(DESCRIBE)命令实例讲解
2016/09/24 PHP
jquery ui dialog里调用datepicker的问题
2009/08/06 Javascript
JS 实现列表与多选框选择附预览动画
2014/10/29 Javascript
Jquery 实现图片轮换
2015/01/28 Javascript
基于javascript实现图片左右切换效果
2016/01/25 Javascript
jQuery实现的简单分页示例
2016/06/01 Javascript
jquery+ajax+text文本框实现智能提示完整实例
2016/07/09 Javascript
学习使用Bootstrap页面排版样式
2017/05/11 Javascript
利用vueJs实现图片轮播实例代码
2017/06/03 Javascript
对于input 框限定输入值为浮点型的js代码
2017/09/25 Javascript
vue生成token保存在客户端localStorage中的方法
2017/10/25 Javascript
Vue入门之数据绑定(小结)
2018/01/08 Javascript
vue实现点击展开点击收起效果
2018/04/27 Javascript
JavaScript实现浅拷贝与深拷贝的方法分析
2018/07/05 Javascript
vue实现购物车抛物线小球动画效果的方法详解
2019/02/13 Javascript
layui使用数据表格实现购物车功能
2019/07/26 Javascript
[02:22]《新闻直播间》2017年08月14日
2017/08/15 DOTA
python Django批量导入不重复数据
2016/03/25 Python
把JSON数据格式转换为Python的类对象方法详解(两种方法)
2019/06/04 Python
python保存log日志,实现用log日志画图
2019/12/24 Python
Python3标准库glob文件名模式匹配的问题
2020/03/13 Python
python3用PyPDF2解析pdf文件,用正则匹配数据方式
2020/05/12 Python
非凡女性奢华谦虚风格:The Modist
2017/10/28 全球购物
《湘夫人》教学反思
2014/02/21 职场文书
2014三八妇女节活动总结
2014/03/01 职场文书
六年级学生评语
2014/04/22 职场文书
《谁的本领大》教后反思
2014/04/25 职场文书
社区国庆节活动总结
2015/03/23 职场文书
爱国主义电影观后感
2015/06/18 职场文书
会议开幕致辞怎么写
2016/03/03 职场文书
学会用Python实现滑雪小游戏,再也不用去北海道啦
2021/05/20 Python
Python使用华为API为图像设置多个锚点标签
2022/04/12 Python