详解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 相关文章推荐
javascript for循环设法提高性能
Feb 24 Javascript
ajax页面无刷新 IE下遭遇Ajax缓存导致数据不更新的问题
Dec 11 Javascript
js中实现多态采用和继承类似的方法
Aug 22 Javascript
js格式化时间小结
Nov 03 Javascript
jquery操作复选框checkbox的方法汇总
Feb 05 Javascript
jquery动态添加删除(tr/td)
Feb 09 Javascript
JS实现带鼠标效果的头像及文章列表代码
Sep 27 Javascript
jQuery Validate表单验证入门学习
Dec 18 Javascript
Spring shiro + bootstrap + jquery.validate 实现登录、注册功能
Jun 02 jQuery
javascript实现二叉树遍历的代码
Jun 08 Javascript
JavaScript事件处理程序详解
Sep 19 Javascript
JavaScript中的全局属性与方法深入解析
Jun 14 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
杏林同学录(二)
2006/10/09 PHP
PHP常用代码大全(新手入门必备)
2010/06/29 PHP
php下通过IP获取地理位置的代码(小偷程序)
2011/06/09 PHP
ThinkPHP快速入门实例教程之数据分页
2014/07/01 PHP
php获取本周开始日期和结束日期的方法
2015/03/09 PHP
PHP封装的字符串加密解密函数
2015/12/18 PHP
PHP框架性能测试报告
2016/05/08 PHP
PHP中empty,isset,is_null用法和区别
2017/02/19 PHP
php实现统计二进制中1的个数算法示例
2018/01/23 PHP
详解PHP中curl_multi并发的实现
2020/06/08 PHP
JS弹出对话框返回值代码(asp.net后台)
2010/12/28 Javascript
jquery实现的一个导航滚动效果具体代码
2013/05/27 Javascript
JavaScript1.6数组新特性介绍以及JQuery的几个工具方法
2013/12/06 Javascript
利用函数的惰性载入提高javascript代码执行效率
2014/05/05 Javascript
jquery中radio checked问题
2015/03/16 Javascript
jquery插件orbit.js实现图片折叠轮换特效
2015/04/14 Javascript
JS+CSS实现的竖向简洁折叠菜单效果代码
2015/10/22 Javascript
使用JS批量选中功能实现更改数据库中的status状态值(批量展示)
2016/11/22 Javascript
loading动画特效小结
2017/01/22 Javascript
详解AngularJS2 Http服务
2017/06/26 Javascript
underscore之Chaining_动力节点Java学院整理
2017/07/10 Javascript
浅析vue中的MVVM实现原理
2019/03/04 Javascript
webpack中的模式(mode)使用详解
2020/02/20 Javascript
vue项目实现多语言切换的思路
2020/09/17 Javascript
Python程序中的观察者模式结构编写示例
2016/05/27 Python
django连接mysql数据库及建表操作实例详解
2019/12/10 Python
jupyter notebook实现显示行号
2020/04/13 Python
瑞士香水购物网站:Parfumcity.ch
2017/01/14 全球购物
英国外籍人士的在线超市:British Corner Shop
2019/06/03 全球购物
开普敦通行证:Cape Town Pass
2019/07/18 全球购物
就业自荐信
2013/12/04 职场文书
激情洋溢的毕业生就业求职信
2014/03/15 职场文书
安全口号大全
2014/06/21 职场文书
2015年护理工作总结范文
2015/04/03 职场文书
详解MySQL InnoDB存储引擎的内存管理
2021/04/08 MySQL
golang中的struct操作
2021/11/11 Golang