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 firefox不显示本地预览图片问题的解决方法
Nov 12 Javascript
基于jquery的超简单上下翻
Apr 20 Javascript
JavaScript高级程序设计 错误处理与调试学习笔记
Sep 10 Javascript
常见表单重复提交问题整理及解决方法
Nov 13 Javascript
JavaScript中的this关键字使用详解
Aug 14 Javascript
JS制作类似选项卡切换的年历
Dec 03 Javascript
xmlplus组件设计系列之按钮(2)
Apr 26 Javascript
9种改善AngularJS性能的方法
Nov 28 Javascript
webpack+vue2构建vue项目骨架的方法
Jan 09 Javascript
jQuery实现经典的网页3D轮播图封装功能【附源码下载】
Feb 15 jQuery
vue项目中全局引入1个.scss文件的问题解决
Aug 01 Javascript
浅析vue中的nextTick
Dec 28 Vue.js
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 cron中的批处理
2008/09/16 PHP
PHP 定界符 使用技巧
2009/06/14 PHP
PHP的构造方法,析构方法和this关键字详细介绍
2013/10/22 PHP
PHP中比较两个字符串找出第一个不同字符位置例子
2014/04/08 PHP
PHP实现指定字段的多维数组排序函数分享
2015/03/09 PHP
PHP使用内置函数生成图片的方法详解
2016/05/09 PHP
PHP利用pdo_odbc实现连接数据库示例【基于ThinkPHP5.1搭建的项目】
2019/05/13 PHP
silverlight线程与基于事件驱动javascript引擎(实现轨迹回放功能)
2011/08/09 Javascript
jQuery遍历Table应用示例
2014/04/09 Javascript
JavaScript及jquey实现多个数组的合并操作
2014/09/06 Javascript
理解jQuery stop()方法
2014/11/21 Javascript
AngularJS中实现用户访问的身份认证和表单验证功能
2016/04/21 Javascript
jQuery验证插件validate使用详解
2016/05/11 Javascript
jquery css实现邮箱自动补全
2016/11/14 Javascript
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
2016/12/15 Javascript
完美实现js选项卡切换效果(二)
2017/03/08 Javascript
利用hasOwnProperty给数组去重的面试题分享
2018/11/05 Javascript
JS数组Object.keys()方法的使用示例
2019/06/05 Javascript
详解为element-ui的Select和Cascader添加弹层底部操作按钮
2020/02/07 Javascript
JS函数本身的作用域实例分析
2020/03/16 Javascript
详解webpack的文件监听实现(热更新)
2020/09/11 Javascript
Python使用BeautifulSoup库解析HTML基本使用教程
2016/03/31 Python
Python装饰器用法实例总结
2018/02/07 Python
sklearn+python:线性回归案例
2020/02/24 Python
django实现将修改好的新模型写入数据库
2020/03/31 Python
洛杉矶时尚女装系列:J.ING US
2019/03/17 全球购物
机修工岗位职责
2013/11/24 职场文书
学生出入校管理制度
2014/01/16 职场文书
《愚公移山》教学反思
2014/02/20 职场文书
啦啦队口号大全
2014/06/16 职场文书
优秀共产党员演讲稿
2014/09/04 职场文书
党委班子纠正“四风”问题整改措施
2014/10/28 职场文书
2014年村计划生育工作总结
2014/11/14 职场文书
房地产置业顾问岗位职责
2015/04/11 职场文书
前台岗位职责范本
2015/04/16 职场文书