JS堆栈和拷贝的理解
来源:互联网 发布:川一硅藻泥怎么样知乎 编辑:程序博客网 时间:2024/06/10 09:50
1.堆栈的概念
栈:
队列优先,先进先出,由操作系统自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈
堆:
先进后出,动态分配的空间一般由程序员分配释放,若程序员不释放,程序结束时可能由OS(Operatig System,管理和控制计算机硬件与软件资源的计算机程序,是直接运行在“裸机”上的最基本的系统软件)回收,分配方式类似于链表
2.基本类型和引用类型
基本类型:
存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配
5种基本数据类型:undefined,Null,Boolean,Number和String,它们是直接按值存放的,所以可以直接访问
引用类型:
存放在堆内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。每个空间大小不一样,要根据情况进行特定的分配。
当我们需要访问引用类型(如对象,数组,函数等)的值,首先从栈中获得该对象的地址指针,然后从堆内存中取得所需要的数据
3.传值与传址的区别
实例一:js中创建两个对象p1,p2,使用赋值法:
function Person(){//创建一个构造函数 this.name = 'zhangsan', this.age = 30}var p1 = new Person();//初始化一个对象,并不需要返回这个对象,自动返回这个对象var p2 = p1;//此时复制堆上p1的地址址给p2,所以现在p1,p2指向堆上同一内存空间console.log(p2.name);//输出zhangsanp2.name = "apple";//此时修改的是p2地址指向的堆上对象的属性值console.log(p1.name);//输出appplep2 = null;//console.log(p2.name);报错,无法找到name这个属性console.log(p1.name);//输出apple
实例二:
var a = [1,2,3,4,5]; var b =a;//此时变量a,b指向同一个堆上的对象var c = a[0];console.log(b);//弹出1,2,3,4,5console.log(c);//弹出1b[4] = 6;//改变的栈上对象c = 7;console.log(a[4]);console.log(a[0]);
当改变b数据,a中数据对应也发生了变化,但是改变c中数据时,a的值并没有发生变化,这就是传值与传址的区别,因为a是数组型,属于引用型,所以它赋给b的时候传的是栈中的地址(相当于新建了一个不同名的“指针”),而不是堆内存中的对象。而c仅仅是从a堆内存中获取了一个数据值,并保存在栈中。所以当b修改时,会根据地址回到a堆中修改,c则直接在栈中修改,并且不能指向a堆内存中
4.浅拷贝
在定义一个数组或者对象,变量存放的往往只是一个 地址。当我们使用对象拷贝时,如果属性是对象或者数组时,这时候我们传递的只是一个地址。因此子对象在访问该属性时,会根据地址回溯到父对象的堆内存中,即意味着父子对象发生了关联,两者的属性值会指向同一个内存空间
var a = { name : "JavaScript"}//使用对象直接量创建一个对象function Copy(p){ var c = {};//创建一个空对象 for(var i in p){//for...in遍历传入对象参数p中所有的属性值 c[i] = p[i]; } return c;}a.author = { firstname:"David", surname:"Flanagan"}//给a新增了一个属性,此属性是一个对象var b = Copy(a);b.key3 = '33333';console.log(b.name);//输入JavaScriptconsole.log(b.key3);//输出33333console.log(a.key3);//输出undefined 4
a对象name是字符串,author是一个对象,当把a拷贝到b中,1,2属性顺利的拷贝到b对象中去,给b对象新增一个字符串类型的属性,b能正常修改,但是a中并无定义,说明了对象的key3(基本类型)并没有关联到父对象中去,所以是undefined
但是
b.author ={ name:dadiaoge;}console.log(a.author);console.log(b.author);//两者都输出改变后的值
所以,当修改的属性变为对象或者数组时,那么父子对象之间会发生关联,即对b对象属性进行修改时,a,b 的author属性值均发生了改变,其在内存中的状态可以用以下图片来表示:
name 属于基本类型,所以拷贝的时候传递的是该数据段。但是author属性是一个对象值,所以author在拷贝的时候传递的是指向该对象的地址,无论复制多少个此属性,其值始终指向父对象author在堆上的内存空间
5.深拷贝
在实际情况中,我们在编码的时候并不希望父子对象之间发生关联,这时候可以用到深度拷贝,既然属性值是对象或者数组的时候,只会传址。那么我们使用递归来解决问题,把所有父对象中所有属于对象的属性类型都遍历赋给子对象就好
function Student(){ this.name = "zhangsan", this.age = 12, this.grade = { English : "good", math : "so" } } var a = new Student;//实例化一个对象 function Copy(p,c){ var c = c || {};//创建一个空对象 for(i in p){//变量p中的属性 if(typeof p[i] === 'object'){//如果p中的这个属性的类型是对象 c[i] = (p[i].constructor === Array)?[]:{};//判断该属性的类型是不是数组类型,判断完毕返回一个类型 Copy(p[i],c[i]);//判断结束完毕之后,遍历p此属性中的属性值并将它赋给新创建的对象的这个属性 } else{ c[i] = p[i]; } } return c; } var b = {}; b = Copy(a,b); b.aihao = { English:"great" } console.log(a);//不改变其原有属性的值(可以通过打断点来自己看一下整个流程)
内存过程如下图:
- JS堆栈和拷贝的理解
- 理解JS的浅拷贝和深拷贝
- JS堆栈与拷贝
- 关于JS堆栈与拷贝
- 深拷贝和浅拷贝的理解?
- 深拷贝和浅拷贝的理解
- 深拷贝和浅拷贝的理解?
- 深拷贝和浅拷贝的理解?
- js的深拷贝和浅拷贝
- iOS堆栈的理解和区别
- copy深拷贝和浅拷贝的理解和使用
- JS中的堆栈与拷贝(转载)
- 对深拷贝和浅拷贝的个人理解
- 对深拷贝和浅拷贝的再次理解
- C++中的深拷贝和浅拷贝的简单理解
- 深拷贝和浅拷贝的理解与应用
- 对于深拷贝和浅拷贝的理解
- js队列和堆栈
- 算法——快速排序
- Java第1周-打印九九乘法表
- java计划
- python零碎知识(6)--魔法方法、属性和迭代器
- C# 依据DataTable创建透视表
- JS堆栈和拷贝的理解
- 全面的Android文件目录解析和获取方法(包含对6.0系统的说明) simen201310 2016-08-28 15:52:12 浏览3290 评论0 移动开发与客户端 android 摘要
- Sony vegas Pro 14 v14.0中文版 附激活说明
- 源码分析Ambari的DAG是如何做的
- 浏览器err_invalid_argument解决方法
- Http TCP/IP UDP socket 解析
- python中函数是否加括号问题
- ccf-火车购票
- 性能测试知多少---响应时间