详解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 相关文章推荐
怎么让脚本或里面的函数在所有图片都载入完毕的时候执行
Oct 17 Javascript
关闭浏览器输入框自动补齐 兼容IE,FF,Chrome等主流浏览器
Feb 11 Javascript
Jquery性能优化详解
May 15 Javascript
Javascript基础教程之定义和调用函数
Jan 18 Javascript
Easyui Treegrid改变默认图标的方法
Apr 29 Javascript
通过bootstrap全面学习less
Nov 09 Javascript
Angular实现一个简单的多选复选框的弹出框指令实例
Apr 25 Javascript
微信小程序获取用户openId的实现方法
May 23 Javascript
详解Vue.js Mixins 混入使用
Sep 15 Javascript
vue通过style或者class改变样式的实例代码
Oct 30 Javascript
微信小程序自定义单项选择器样式
Jul 25 Javascript
vue实现导航标题栏随页面滚动渐隐渐显效果
Mar 12 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
php判断输入不超过mysql的varchar字段的长度范围
2011/06/24 PHP
一个基于phpQuery的php通用采集类分享
2014/04/09 PHP
详解PHP的Yii框架中自带的前端资源包的使用
2016/03/31 PHP
php 伪造HTTP_REFERER页面URL来源的三种方法
2016/09/22 PHP
PHP registerXPathNamespace()函数讲解
2019/02/03 PHP
js传值 判断
2006/10/26 Javascript
JavaScript子类用Object.getPrototypeOf去调用父类方法解析
2013/12/05 Javascript
js实现的二分查找算法实例
2016/01/21 Javascript
JS从数组中随机取出几个数组元素的方法
2016/08/02 Javascript
微信小程序 icon组件详细及实例代码
2016/10/25 Javascript
谈谈jQuery之Deferred源码剖析
2016/12/19 Javascript
Nodejs中使用captchapng模块生成图片验证码
2017/05/18 NodeJs
详解vue+webpack+express中间件接口使用
2018/07/17 Javascript
详解微信小程序调用支付接口支付
2019/04/28 Javascript
Vue中el-form标签中的自定义el-select下拉框标签功能
2020/04/20 Javascript
js实现弹窗效果
2020/08/09 Javascript
Vue检测屏幕变化来改变不同的charts样式实例
2020/10/26 Javascript
[02:42]2014DOTA2国际邀请赛 三冰专访:我会打到Ti20
2014/07/13 DOTA
[54:30]Liquid vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
举例介绍Python中的25个隐藏特性
2015/03/30 Python
利用python爬取软考试题之ip自动代理
2017/03/28 Python
python使用pandas实现数据分割实例代码
2018/01/25 Python
Python获取航线信息并且制作成图的讲解
2019/01/03 Python
python如何实现数据的线性拟合
2019/07/19 Python
Django 权限认证(根据不同的用户,设置不同的显示和访问权限)
2019/07/24 Python
Pycharm中import torch报错的快速解决方法
2020/03/05 Python
Java如何基于wsimport调用wcf接口
2020/06/17 Python
美国知名玩具品牌:Melissa & Doug
2016/08/16 全球购物
Kipling凯浦林美国官网:世界著名时尚休闲包袋品牌
2016/08/24 全球购物
小学中秋节活动方案
2014/02/06 职场文书
个人廉洁自律承诺书
2014/03/27 职场文书
促销活动总结范文
2014/04/30 职场文书
煤矿安全知识竞赛活动总结
2014/07/07 职场文书
个人学习党的群众路线教育实践活动心得体会
2014/11/05 职场文书
总经理助理岗位职责
2015/01/31 职场文书
PYTHON基于Pyecharts绘制常见的直角坐标系图表
2022/04/28 Python