详解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代码
Jan 01 Javascript
jquery实现文本框数量加减功能的例子分享
May 10 Javascript
JavaScript实现自动变换表格边框颜色
May 08 Javascript
js+css实现超简洁的二级下拉菜单效果代码
Sep 07 Javascript
微信小程序小组件 基于Canvas实现直播点赞气泡效果
May 29 Javascript
Node.js实现文件上传的示例
Jun 28 Javascript
angular.js4使用 RxJS 处理多个 Http 请求
Sep 23 Javascript
利用angular、react和vue实现相同的面试题组件
Feb 19 Javascript
微信小程序调用摄像头隐藏式拍照功能
Aug 22 Javascript
详解vue-cli下ESlint 配置说明
Sep 03 Javascript
简单了解JavaScript异步
May 23 Javascript
javascript数组includes、reduce的基本使用
Jul 02 Javascript
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
将数组写入txt文件 var_export
2009/04/21 PHP
PHP实现采集中国天气网未来7天天气
2014/10/15 PHP
ThinkPHP安装和设置
2015/07/27 PHP
用HTML/JS/PHP方式实现页面延时跳转的简单实例
2016/07/18 PHP
php微信公众平台开发之微信群发信息
2016/09/13 PHP
默认让页面的第一个控件选中的javascript代码
2009/12/26 Javascript
基于jQuery判断两个元素是否有重叠部分的代码
2012/07/25 Javascript
JS+CSS实现简易实用的滑动门菜单效果
2015/09/18 Javascript
jQuery实用技巧必备(中)
2015/11/03 Javascript
JavaScript中函数表达式和函数声明及函数声明与函数表达式的不同
2015/11/15 Javascript
JS实现倒计时(天数、时、分、秒)
2016/11/16 Javascript
javascript 中关于array的常用方法详解
2017/05/05 Javascript
vue-resource 拦截器(interceptor)的使用详解
2017/07/04 Javascript
微信小程序实现手指触摸画板
2018/07/09 Javascript
Vue-Quill-Editor富文本编辑器的使用教程
2018/09/21 Javascript
nuxt+axios实现打包后动态修改请求地址的方法
2020/04/22 Javascript
python 域名分析工具实现代码
2009/07/15 Python
Python、Javascript中的闭包比较
2015/02/04 Python
在Python中利用Into包整洁地进行数据迁移的教程
2015/03/30 Python
Python中使用logging模块打印log日志详解
2015/04/05 Python
解读Python编程中的命名空间与作用域
2015/10/16 Python
利用python实现数据分析
2017/01/11 Python
Python正则表达式经典入门教程
2017/05/22 Python
python实现TF-IDF算法解析
2018/01/02 Python
Python实现基于KNN算法的笔迹识别功能详解
2018/07/09 Python
kafka-python批量发送数据的实例
2018/12/27 Python
PyCharm下载和安装详细步骤
2019/12/17 Python
Python运行异常管理解决方案
2020/03/09 Python
css 省略号 css3让多余的字符串消失并附加省略号的实现代码
2013/02/07 HTML / CSS
应届生个人求职信模板
2013/11/26 职场文书
中学教师暑期培训方案
2014/08/27 职场文书
教师网络培训心得体会
2016/01/09 职场文书
2019暑期安全倡议书!
2019/06/27 职场文书
ES6 解构赋值的原理及运用
2021/05/25 Javascript
SpringMVC 整合SSM框架详解
2021/08/30 Java/Android
基于Python实现一个春节倒计时脚本
2022/01/22 Python