由js深拷贝引起的对内存空间的一些思考
数据类型
js常用数据类型分为基本类型和引用类型
- 基本类型:null、undefined、数值型、字符串型、布尔型
- 引用类型:数组、对象
内存空间
var a = [1, 2, 3];
var b = a;
b[2] = 4;
a; // ??
我们都知道结果是[1, 2, 4],因为b和a指向了同一个引用对象所以都可以改变该对象的值,我们用内存空间来深入理解一下。
我们知道在内存中存在两块区域,一个是栈stack,一个是堆heap。 通常我们的基本数据类型存储在栈中,而我们的引用数据类型存于堆中。栈中会有一个指针指向存在于堆中的数据以便于引用。
var arr = [1, 2, 3];
内存图应该是这样:
这时候会出现一个问题:允许两个指针指向同一个堆数据,这意味着通过其中一个指针篡改了数值那么会影响另一个指针。
var a = [1, 2, 3];
var b = a;
以上变量在内存中的图是这样的:
说个题外话:了解这一机制对理解prototype是有很大好处的
function Person(name) {
this.name = name;
}
Person.prototype = {
sayHi() {
console.log("hi, " + this.name);
}
}; var p1 = new Person('lan');
p1.sayHi(); // 'hi, lan'
内存图如下,可以自己理解一下,找一找哪些存在于stack哪些存在于heap:
接上述,直接将a赋值为b这样为浅拷贝,而上上图中则为深拷贝。
js实现深拷贝思路:
- 先判断所赋值的类型,如果为基本类型则直接拷贝,若为对象类型则在heap中重新生成一个对象,再递归的将值赋值过去。
function deepCopy(obj) {
var result = ''; // 为基本类型
if(obj == null || obj == undefined || typeof obj != 'object')
return obj; // 为引用类型,判断为数组还是为对象
if(obj instanceof Array)
result = [];
else
result = {}; for(var key in obj) {
var current = obj[key];
if(current == null || current == undefined || typeof current != 'object')
result[key] = current;
else
// 不直接调用deepCopy而用arguments.callee
// 以避免函数被赋值给其他变量而出现错误
result[key] = arguments.callee(current);
} return result;
} var a = {
name: 'lan',
age: 20,
birth: [1,2,3,4],
like: {
food: 'fruit',
color: ['pink', 'blue']
}
}; var b = deepCopy(a);
b.birth[2] = 5;
a.birth; // [1, 2, 3, 4]
以上为自己对于指针的一点思考,欢迎指正与扩展。
由js深拷贝引起的对内存空间的一些思考的更多相关文章
- js基础梳理-内存空间
我估计有很多像我这样非计算机专业的人进入到前端之后,总是在写业务代码,思考什么什么效果如何实现,导致很多基础概念型的东西都理解得并不太清楚.经常一碰到群里讨论的些笔试题什么的,总觉得自己像是一个假前端 ...
- js中的栈、堆、队列、内存空间
栈(stack) .堆(heap). 队列(queue)是js的三种数据结构. 栈(stack) 栈的特点是"LIFO,即后进先出(Last in, first out)".数据存 ...
- JS 从内存空间谈到垃圾回收机制
壹 ❀ 引 从事计算机相关技术工作的同学,对于内存空间相关概念多少有所耳闻,毕竟像我这种非计算机科班出身的人,对于栈堆,垃圾回收都能简单说道几句:当我明白JS 基本类型与引用类型数据存储方式不同,才 ...
- js内存空间的那点事
由于js具有自动垃圾回收机制,导致接触js后一直没去关注js的内存分配及变量回收等原理,只是懵懂的了解用变量标记法(null)可以手动的去清除或是回收:是时候弥补这个大坑了... 垃圾回收两种方法 一 ...
- JS进阶之---基本数据类型,引用类型,内存空间
一.内存空间: 为了便于理解,我们暂且先将Js的内存分为栈内存和堆内存. JavaScript具有垃圾自动回收机制,内存的分配与回收都完全实现了自动管理.所以我们在开发时一般会忽视内存空间的问题.但是 ...
- JS进阶系列之内存空间
也许很多人像我一样,觉得JS有垃圾回收机制,内存就可以不管了,以至于在全局作用域下定义了很多变量,自以为JS会自动回收,直到最近,看了阮一峰老师,关于javascript内存泄漏的文章时,才发现自己写 ...
- 11.1 js中级,数据类型、数据储存方式、作用域内存空间的区别以及例识别。
一. 基本数据类型和引用数据类型的区别. 1.基本数据类型:基本数据类型就是简单的操作值. 2.引用数据类型:就是把引用的地址赋给变量. 堆内存: 就是存放代码块的,存放形式有两种 1)对象以键值对的 ...
- js内存空间详细图解-笔记
原文参考http://mp.weixin.qq.com/s/NGqdjhoU3MR9LD0yH6tKIw 栈-先进后出堆-类比成书于书架(形象),只要知道Key就可以找到value 基础数据类型(Un ...
- JS内存空间详细图解
JS内存空间详细图解 变量对象与堆内存 var a = 20; var b = 'abc'; var c = true; var d = { m: 20 } 因为JavaScript具有自动垃圾回收机 ...
随机推荐
- ubuntu14.04安装、NVIDIA显卡驱动安装及CUDA8.0、Cudnn5.1的环境搭建
安装环境:hp-Z440工作站.64位Ubuntu14.04(64位Ubuntu16.04).Cuda8.0.Cudnn5.1.Nvidia GeForce GT 705.Tesla K40c 本文可 ...
- setfacl命令 来自: http://man.linuxde.net/setfacl
常用选项##### <pre>-b,--remove-all:删除所有扩展的acl规则,基本的acl规则(所有者,群组,其他)将被保留. -k,--remove-default:删除缺省的 ...
- Docker Centos7 下建立 Docker 桥接网络
为什么要让docker桥接物理网络? docker默认提供了一个隔离的内网环境,启动时会建立一个docker0的虚拟网卡,每个容器都是连接到docker0网卡上的.而docker0的ip段为172.1 ...
- 原创~vue router-link添加点击事件
在学习vue中会遇到给router-link添加@click,@mouseover等事件 我想要做的是用v-for循环输出导航菜单,但是下面代码的@click事件和@mouseover并不会响应 &l ...
- Python中高阶函数sorted()用法
在Python中,有内置的排序方法:sorted(iterable, key, reverse). Sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序.key指定的函数 ...
- 统计输入的汉字,数字,英文,other数量
主要用正则表达式在完成对汉字,数字,英文数量的验证. import java.util.Scanner; /* * 统计汉字,数字,英文,other * */ public class Test { ...
- VSCode插件MSSQL教程(昨天提了一下)
推荐一个跨平台SQL IDE:https://docs.microsoft.com/zh-cn/sql/sql-operations-studio/download 什么数据库都木有(系统自带的不算) ...
- FLEX类似谷歌地图拖拽功能
要实现类似于谷歌地图拖拽功能,可以用s:Scroller标签来实现,代码如下: mxml: <s:Scroller width="100%" height="100 ...
- 使用commons-csv简单读写CSV文件
文章首发于我的github博客 需求 客户的开发测试环境将做迁移.因此需要对zookeeper上的重要的数据以CSV文件格式做备份. 本文通过Apache的commons-csv操作CSV文件.官网地 ...
- nyoj234 吃土豆 01背包
思路:假设我们先只考虑一行,规则就是取了i处的土豆,每一个土豆有两种选择,拿与不拿,那么i-1和i+1处的土豆都不能再取,那么要求某一行的最大取值就用一次动态规划即可,dp(i)表示前i个土豆能取得的 ...