JS堆与栈 拷贝
2019-01-11 15:09
106 查看
搜了一些教程,归类整理
栈(stack)和堆(heap)
- stack为自动分配的内存空间,它由系统自动释放;
- heap则是动态分配的内存,大小不定也不会自动释放
JS中有基本类型和引用类型
- 基本类型:Undefined、Null、Boolean、Number 和 String。存放在栈内存中的简单数据段,直接按值存放的。 直接访问
-
访问,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据
传值与传址
- 前面之所以要说明什么是内存中的堆、栈以及变量类型,就是为了更好的理解什么是“浅拷贝”和“深拷贝”。
- 基本类型与引用类型最大的区别实际就是传值与传址的区别
基本类型
var a = 1; var b =a; b=2; console.log(a,b) // 1 2
引用类型
var c = [1,2,3,4]; var d =c; d[0]=2; console.log(c,d) // [2,2,3,4] [2,2,3,4]
声明一个基本类型,都会在栈里新开辟一个新空间,哪怕值一样,存放值,所以var a ,var b=a 时,有两个,之后改值是互不影响的。
但声明一个引用类型,变量是定义的地址指针,所以 var d= c,导致地址指针是一样的,都同时指向堆里的同一个存储空间
浅拷贝和深拷贝
浅拷贝的时候如果数据是基本数据类型,那么就如同直接赋值那种,会拷贝其本身,如果除了基本数据类型之外还有一层对象,那么对于浅拷贝而言就只能拷贝其引用,对象的改变会反应到拷贝对象上;但是深拷贝就会拷贝多层,即使是嵌套了对象,也会都拷贝出来。所以会有人粗略地说:浅拷贝是一层,深拷贝是多层。如果拷贝不彻底,改变新数组中嵌套的引用对象,原数据会改变。
浅拷贝
基本类型数据互不影响,虽然拷贝对象一开始新建,但浅拷贝里面的引用类型的地址指针是同一个
方法一
var obj1 = { a:1, b:true, c:"hello world", d:function(){ console.log("我是一个方法") }, e:[1,2,3], f:{ g:1, h:"我是一个h", i:{ j:2, k:3 } }, } function shallowCopy(obj){ var objCopy ={}; for (var i in obj){ objCopy[i]=obj[i] } return objCopy } var obj2 = shallowCopy(obj1) console.log(obj1,obj2)
如果我们改变值呢
obj2.a=2 obj2.b=false obj2.e=[4,5,6] obj2.f.g=3 console.log(obj1,obj2)
方法二
ES6中的Object.assign方法,Object.assign是ES6的新函数。Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是Object.assign() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
//target:目标对象。 //sources:任意多个源对象。 //返回值:目标对象会被返回 Object.assign(target, ...sources)
var obj2 = Object.assign({}, obj1)
深拷贝
新旧数据互不干涉
方法一
一层一层赋值,不建议
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c }; obj2.b = 100; console.log(obj1); // { a: 10, b: 20, c: 30 } console.log(obj2); // { a: 10, b: 100, c: 30 }
方法二
用JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象
只有可以转成JSON格式的对象才可以这样用,像function没办法转成JSON
JSON.parse(JSON.stringify(obj))
var obj1 = { a:1, b:true, c:"hello world", d:function(){ console.log("我是一个方法") }, e:[1,2,3], f:{ g:1, h:"我是一个h", i:{ j:2, k:3 } }, } var obj2 = JSON.parse(JSON.stringify(obj1)); obj2.a = 20; obj2.f.g =3 console.log(obj1,obj2); console.log(obj1 === obj2); // false console.log(obj1.f === obj2.f); // false
方法三
递归
function shallowCopy(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况 if(prop === obj) { continue; } if (typeof prop === 'object') { obj[i] = (prop.constructor === Array) ? [] : {}; shallowCopy(prop, obj[i]); } else { obj[i] = prop; } } return obj; } var str = {}; var obj = { a: {a: "hello", b: 21} }; shallowCopy(obj, str); console.log(str.a);
方法四
直接使用var newObj = Object.create(oldObj),可以达到深拷贝的效果
var obj1 = { a:1, b:true, c:"hello world", d:function(){ console.log("我是一个方法") }, e:[1,2,3], f:{ g:1, h:"我是一个h", i:{ j:2, k:3 } }, } function shallowCopy(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况 if(prop === obj) { continue; } if (typeof prop === 'object') { obj[i] = (prop.constructor === Array) ? [] : Object.create(prop); } else { obj[i] = prop; } } return obj; } console.log(deepClone(obj1,{}))
改变值
var test = shallowCopy(obj1,{}); test.a=2 test.f.g=3
如有问题,欢迎斧正
相关文章推荐
- Js中的深拷贝与浅拷贝
- JS深拷贝引用类型数据
- js 对象浅拷贝、深拷贝
- js 数组拷贝
- JS实现深拷贝
- JS 深拷贝 /深克隆
- JS的深拷贝和浅拷贝
- win7下,Ant 配合yuicompressor对js和css进行合并、压缩、拷贝处理
- js深拷贝与浅拷贝
- js中数组拷贝失败
- 【JS】深拷贝 vs 浅拷贝
- 【深拷贝/浅拷贝】javascript的深拷贝和浅拷贝 分类: js javascript深拷贝 深拷贝浅拷贝 javascript 2015-08-10 11:29 7人阅读 评论(0) 收藏
- js - 深拷贝
- 理解JS的浅拷贝和深拷贝
- JS深拷贝继承
- 前端之js之深拷贝和浅拷贝
- Node.js的学习日记 图片简单下载和拷贝功能的实现 简单下载和拷贝
- js 数组深浅拷贝 indexOf处理一个数组在;另一个数组中的索引
- js文件,同样的路径,拷贝过来的为什么不能访问
- js 中 对数组和对象 的 深拷贝 方法