详解JavaScript的内存空间、赋值和深浅拷贝


Posted in Javascript onApril 17, 2019

JavaScript的内存空间

在JavaScript中,每一个数据都需要一个内存空间。内存空间分为两种,栈内存(stack)与堆内存(heap)

栈是系统自动分配的内存空间,由系统自动释放,堆则是动态分配的内存,大小不定不会自动释放。

基础数据类型

JavaScript中的基础数据类型,这些值都有固定的大小,保存在栈内存中,由系统自动分配存储空间在栈内存空间的值,我们可以直接进行操作,因此基础数据类型都是按照值访问

在栈内存中的数据发生复制的行为时,系统会自动为新变量开辟一个新的内存空间,当复制执行后,两个内存空间的值就互不影响,改变其中一个不会影响另一个

栈内存空间数据复制示例
var a = `I am variable a`;
var b = a; 
console.log(b); //`I am variable a`
b = `I am variable b`;
console.log(a); //`I am variable a`
console.log(b); //`I am variable b`

引用数据类型

引用类型的值是保存在堆内存中的对象,在JavaScript中我们不能直接操作对象的堆内存空间。因为引用类型的值都是按引用访问的,所以在操作对象时,实际上是操作对象的引用而不是实际的对象。引用可以理解为保存在栈内存中的一个地址,该地址指向堆内存中的一个实际对象

引用类型值的复制,系统会为新的变量自动分配一个新的栈内存空间这个栈内存空间保存着与被复制变量相同的指针,尽管他们在栈内存中的内存空间的位置互相独立但是在堆内存中访问到的对象实际上是同一个,因此,当我们改变其中一个对象的值时,实际上就是改变原来的对象

栈内存空间保存指针(地址),堆内存空间保存实际的对象,我们通过变量访问对象时,实际上访问的是对象的引用(地址)

内存中的栈区域存放变量(基本类型的变量包括变量声明和值)以及指向堆区域存储位置的指针(引用类型的变量包括变量声明和指向内容的指针)

var a = {
  name : `I am object a`,
  type : 'object'
}

var b = a;
console.log(b);
// {name: "I am object a", type: "object"}

b.name = `I am object b`;

console.log(a);
// {name: "I am object b", type: "object"}

console.log(b);

// {name: "I am object b", type: "object"}

基本类型总结

基本数据类型:

包括:null、undefined、number、string、boolean、symbol(es6)

存放位置:内存中的栈区域中

比较:值的比较,判断是否相等,如果值相等,就相等。一般使用===进行比较,因为==会进行类型的转换

拷贝:赋值(通过(=)赋值操作符 赋值),赋值完成后,两个变量之间就没有任何关系了,改变其中一个变量的值对另一个没有任何影响

引用类型总结

引用数据类型:

包括:数组、对象、函数

存放位置:内存的栈区域中存放变量和指针,堆区域存储实际的对象

比较:是引用的比较(就是地址的比较,变量在栈内存中对应的指针地址相等就指向同一个对象)判断是否为同一个对象,示例如下

变量a和变量b的引用不同,对象就不是同一个对象
var a = {name:'Jay'};
var b = {name:'Jay'};
a===b //false

我们对JavaScript中引用类型进行操作的时候,都是操作其对象的引用(保存在栈内存中的指针)

赋值、深拷贝和浅拷贝 (Assignment, deep copy and shallow copy)

赋值:两个变量的值(指针)都指向同一个对象,改变其中一个,另一个也会受到影响

所谓拷贝就是复制,通过复制原对象生成一个新的对象

浅拷贝:重新在堆内存中开辟一个空间,拷贝后新对象获得一个独立的基本数据类型数据,和原对象共用一个原对象内的引用类型数据,改变基本类型数据,两个对象互不影响,改变其中一个对象内的引用类型数据,另一个对象会受到影响

var obj = {
  name: 'Jay Chou',
  age: 32,
  song:{
    name:'发如雪',
    year:2007
  }
}
var obj1 = obj;
function shallowCopy(obj){
  var scObj = {};
  for(var prop in obj){
    if(obj.hasOwnProperty(prop)){
      scObj[prop] = obj[prop]
    }
  }
  return scObj;
}
var obj2 = shallowCopy(obj);
console.log(obj === obj1,'obj === obj1','赋值');
console.log(obj === obj2,'obj === obj2','浅拷贝');
// true "obj === obj1" "赋值"
// false "obj === obj2" "浅拷贝"
console.log(obj.song === obj2.song);
//true
obj2.song.name='双截棍';
obj2.name='Jay';
console.log(obj)
// {name: "Jay Chou", age: 32, song: {name:'双截棍',year:2007}}
console.log(obj1);
// {name: "Jay Chou", age: 32, song: {name:'双截棍',year:2007}}
console.log(obj2);
{name: "Jay", age: 32, song: {name:'双截棍',year:2007}}
console.log(obj===obj1)
//true
console.log(obj===obj2)
//false

深拷贝:不论是对象内的基本类型还是引用类型都被完全拷贝,拷贝后两个对象互不影响

一种比较简单实现方法是使用var dcObj = JSON.parse(JSON.stringify(obj))

var obj = {
  name: 'Jay Chou',
  age: 32,
  song:{
    name:'发如雪',
    year:2007
  }
}

var dcObj=JSON.parse(JSON.stringify(obj));

console.log(dcObj);
// {name: "Jay Chou", age: 32, song: {name:'发如雪',year:2007}}
console.log(dcObj.song === obj.song);
//false
dcObj.name='Jay';
dcObj.song.name='双截棍';
console.log(obj);
// {name: "Jay Chou", age: 32, song: {name:'发如雪',year:2007}}
console.log(dcObj);
//{name: "Jay", age: 32, song: {name:'双截棍',year:2007}}

比较:赋值、深拷贝、浅拷贝

赋值:新对象仍然指向原对象,改变新对象的基本类型和引用类型的值都会使原对象对应的值一同改变

浅拷贝:改变新对象基本类型的值不会使原对象对应的值一起改变,但是改变新对象引用类型的值会使原对象对应的值一同改变

深拷贝:改变新对象基本类型和引用类型的值,都不会影响原对象,两者互相独立,互不影响

以上所述是小编给大家介绍的JavaScript的内存空间、赋值和深浅拷贝详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
js判断屏幕分辨率的代码
Jul 16 Javascript
JQuery中extend使用介绍
Mar 13 Javascript
使用Bootstrap + Vue.js实现添加删除数据示例
Feb 27 Javascript
全选复选框JavaScript编写小结(附代码)
Aug 16 Javascript
js与jQuery实现的用户注册协议倒计时功能实例【三种方法】
Nov 09 jQuery
angular项目中bootstrap-datetimepicker时间插件的使用示例
Mar 15 Javascript
记一次webapck4 配置文件无效的解决历程
Sep 19 Javascript
vue的keep-alive中使用EventBus的方法
Apr 23 Javascript
mpvue小程序循环动画开启暂停的实现方法
May 15 Javascript
JavaScript实现的开关灯泡点击切换特效示例
Jul 08 Javascript
vue视频播放插件vue-video-player的具体使用方法
Nov 08 Javascript
vue项目中的支付功能实现(微信支付和支付宝支付)
Feb 18 Vue.js
Vue源码探究之虚拟节点的实现
Apr 17 #Javascript
ES6知识点整理之数组解构和字符串解构的应用示例
Apr 17 #Javascript
ES6知识点整理之对象解构赋值应用示例
Apr 17 #Javascript
ES6知识点整理之函数对象参数默认值及其解构应用示例
Apr 17 #Javascript
仿vue-cli搭建属于自己的脚手架的方法步骤
Apr 17 #Javascript
一篇文章,教你学会Vue CLI 插件开发
Apr 17 #Javascript
ES6知识点整理之函数数组参数的默认值及其解构应用示例
Apr 17 #Javascript
You might like
Laravel 实现密码重置功能
2018/02/23 PHP
PHP children()函数讲解
2019/02/03 PHP
Laravel5.0+框架邮件发送功能实现方法图文与实例详解
2019/04/23 PHP
实现连缀调用的map方法(prototype)
2009/08/05 Javascript
如何实现chrome浏览器关闭页面时弹出“确定要离开此面吗?”
2015/03/05 Javascript
JavaScript模拟深蓝vs卡斯帕罗夫的国际象棋对局示例
2015/04/22 Javascript
JavaScript实现简单的tab选项卡切换
2016/01/05 Javascript
基于javascript制作微博发布栏效果
2016/04/04 Javascript
jQuery的文档处理程序详解
2016/05/10 Javascript
5种JavaScript脚本加载的方式
2017/01/16 Javascript
Node.js+jade+mongodb+mongoose实现爬虫分离入库与生成静态文件的方法
2017/09/20 Javascript
父组件中vuex方法更新state子组件不能及时更新并渲染的完美解决方法
2018/04/25 Javascript
mpvue实现微信小程序快递单号查询代码
2020/04/03 Javascript
js实现随机点名
2021/01/19 Javascript
Python 执行字符串表达式函数(eval exec execfile)
2014/08/11 Python
python简单实现基数排序算法
2015/05/16 Python
利用Python-iGraph如何绘制贴吧/微博的好友关系图详解
2017/11/02 Python
解决pycharm运行时interpreter为空的问题
2018/10/29 Python
Python多线程应用于自动化测试操作示例
2018/12/06 Python
Django框架组成结构、基本概念与文件功能分析
2019/07/30 Python
代码总结Python2 和 Python3 字符串的区别
2020/01/28 Python
详解python实现可视化的MD5、sha256哈希加密小工具
2020/09/14 Python
教你使用Sublime text3搭建Python开发环境及常用插件安装另分享Sublime text3最新激活注册码
2020/11/12 Python
Python 按比例获取样本数据或执行任务的实现代码
2020/12/03 Python
使用canvas绘制超炫时钟
2014/12/17 HTML / CSS
美国畅销的跑步机品牌:ProForm
2017/02/06 全球购物
泰海淘:泰国king Power王权免税集团旗下跨境海淘综合型电商
2020/07/26 全球购物
求职简历的自我评价
2014/01/31 职场文书
潘婷洗发水广告词
2014/03/14 职场文书
房产公证委托书范本
2014/09/20 职场文书
党员对十八届四中全会的期盼思想汇报范文
2014/10/17 职场文书
2014年小学德育工作总结
2014/12/05 职场文书
深入理解margin塌陷和margin合并的解决方案
2021/06/26 HTML / CSS
PostgreSQL自动更新时间戳实例代码
2021/11/27 PostgreSQL
mysql聚集索引、辅助索引、覆盖索引、联合索引的使用
2022/02/12 MySQL
Vue+Flask实现图片传输功能
2022/04/01 Vue.js