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 相关文章推荐
firefox firebug中文入门教程 脚本之家新年特别版
Jan 02 Javascript
轻量级 JS ToolTip提示效果
Jul 20 Javascript
jQuery实现鼠标经过图片预览大图效果
Apr 10 Javascript
jquery库文件略庞大用纯js替换jquery的方法
Aug 12 Javascript
javascript实现将文件保存到本地方法汇总
Jul 26 Javascript
jQuery实现背景弹性滚动的导航效果
Jun 01 Javascript
AngularJS表单详解及示例代码
Aug 17 Javascript
解决webpack -p压缩打包react报语法错误的方法
Jul 03 Javascript
JS实现颜色的10进制转化成rgba格式的方法
Sep 04 Javascript
JS实现读取xml内容并输出到div中的方法示例
Apr 19 Javascript
Koa2微信公众号开发之本地开发调试环境搭建
May 16 Javascript
vue中的v-model原理,与组件自定义v-model详解
Aug 04 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 gzip压缩输出的实现方法
2013/04/27 PHP
修改php.ini以达到屏蔽错误信息并记录日志
2013/06/16 PHP
WordPress网站性能优化指南
2015/11/18 PHP
php array_walk 对数组中的每个元素应用用户自定义函数详解
2016/11/18 PHP
PHP实现创建微信自定义菜单的方法示例
2017/07/14 PHP
jquery创建div 实现代码
2009/04/27 Javascript
关于jquery ajax 调用带参数的webservice返回XML数据一个小细节
2012/07/31 Javascript
基于jquery实现后台左侧菜单点击上下滑动显示
2013/04/11 Javascript
js控制table合并具体实现
2014/02/20 Javascript
JQuery中基础过滤选择器用法实例分析
2015/05/18 Javascript
JavaScript过滤字符串中的中文与空格方法汇总
2016/03/07 Javascript
微信小程序 教程之wxapp视图容器 swiper
2016/10/19 Javascript
jQuery grep()方法详解及实例代码
2016/10/30 Javascript
JavaScript交换两个变量值的七种解决方案
2016/12/01 Javascript
js判断一个字符串是以某个字符串开头的简单实例
2016/12/27 Javascript
iscroll-probe实现下拉刷新和下拉加载效果
2017/06/28 Javascript
在vue中使用v-bind:class的选项卡方法
2018/09/27 Javascript
如何为你的JS项目添加智能提示与类型检查详解
2019/03/12 Javascript
Vue 自适应高度表格的实现方法
2020/05/13 Javascript
python在linux系统下获取系统内存使用情况的方法
2015/05/11 Python
PyQt5的安装配置过程,将ui文件转为py文件后显示窗口的实例
2019/06/19 Python
Python爬虫抓取技术的一些经验
2019/07/12 Python
selenium2.0中常用的python函数汇总
2019/08/05 Python
用Python绘制漫步图实例讲解
2020/02/26 Python
Python爬取梨视频的示例
2021/01/29 Python
详解css3中的伪类before和after常见用法
2020/11/17 HTML / CSS
Talbots官网:美国成熟女装品牌
2019/11/15 全球购物
哈萨克斯坦最大的时装、鞋子和配饰在线商店:Lamoda.kz
2019/11/19 全球购物
大学生素质拓展活动方案
2014/02/11 职场文书
建筑安全员岗位职责
2014/03/13 职场文书
公司承诺函范文
2015/01/21 职场文书
旅游项目合作意向书
2015/05/08 职场文书
导游词之无锡唐城
2019/12/12 职场文书
Python集合set()使用的方法详解
2022/03/18 Python
TV动画《间谍过家家》公开PV
2022/03/20 日漫
把77A收信机改造成收音机
2022/04/05 无线电