基本类型 & 引用类型
ecmascript中的数据类型可分为两种:
基本类型:undefined,null,boolean,string,number,symbol
引用类型:object,array,date,function,regexp等
不同类型的存储方式:
基本类型:基本类型值在内存中占据固定大小,保存在栈内存中
引用类型:引用类型的值是对象,保存在堆内存中,而栈内存存储的是对象的变量标识符以及对象在堆内存中的存储地址
不同类型的复制方式:
基本类型
基本类型:从一个变量向另外一个新变量复制基本类型的值,会创建这个值的一个副本,并将该副本复制给新变量
let foo = 1;let bar = foo;console.log(foo === bar); // -> true// 修改foo变量的值并不会影响bar变量的值let foo = 233;console.log(foo); // -> 233console.log(bar); // -> 1
引用类型:从一个变量向另一个新变量复制引用类型的值,其实复制的是指针,最终两个变量最终都指向同一个对象
let foo = { name: 'leeper', age: 20}let bar = foo;console.log(foo === bar); // -> true// 改变foo变量的值会影响bar变量的值foo.age = 19;console.log(foo); // -> {name: 'leeper', age: 19}console.log(bar); // -> {name: 'leeper', age: 19}
深拷贝 & 浅拷贝浅拷贝:仅仅是复制了引用,彼此之间的操作会互相影响
深拷贝:在堆中重新分配内存,不同的地址,相同的值,互不影响
浅拷贝举一个例子()
var me = { name: 'zjj', age: 19, address: { home: 'tianjin' } }; var me_1 = { m_token: 'new' }; function extend(p, c){ var c = c || {}; for(var i in p) { c[i] = p[i]; } } extend(me,me_1);
深拷贝 var me = { name: 'zjj', age: 19, address: { home: 'tianjin' } }; var me_1 = { m_token: 'new' }; function extend(p, c){ var c = c || {}; for(var i in p) { c[i] = p[i]; } } function extenddeeply(p, c) { var c = c || {}; for(var i in p) { if(typeof p[i] === 'object') { // 引用类型需要递归实现深拷贝 c[i] = (p[i].constructor === array ) ? [] : {} extenddeeply(p[i], c[i]); } else { // 非引用类型直接复制即可 c[i] = p[i]; } } } extenddeeply(me,me_1);
json.parse()和json.stringify()
json.stringify():把一个js对象序列化为一个json字符串
json.parse():把json字符串反序列化为一个js对象let obj = { name: 'leeper', age: 20, friend: { name: 'lee', age: 19 }};let copyobj = json.parse(json.stringify(obj));obj.name = 'sandman';obj.friend.name = 'jerry';console.log(obj);// -> {name: sandman, age: 20, friend: {age: 19,name: 'jerry'}}console.log(copyobj);// -> {name: leeper, age: 20, friend: {age: 19,name: 'lee'}}
综上,json.parse()和json.stringify()是完全的深拷贝。
动手实现深拷贝 利【递归】来实现对对象或数组的深拷贝。递归思路:对属性中所有引用类型的值进行遍历,直到是基本类型值为止。
// 深拷贝function deepcopy(obj) { if (!obj && typeof obj !== 'object') { throw new error('error arguments'); } // const targetobj = obj.constructor === array ? [] : {}; const targetobj = array.isarray(obj) ? [] : {}; for (let key in obj) { //只对对象自有属性进行拷贝 if (obj.hasownproperty(key)) { if (obj[key] && typeof obj[key] === 'object') { targetobj[key] = deepcopy(obj[key]); } else { targetobj[key] = obj[key]; } } } return targetobj;}
拷贝方式其实也是一种继承的方式,当然继承还是有其他方法的!
相关推荐:
js中浅拷贝与深拷贝的简单介绍以及实现方法
js执行机制的概念?js的执行机制的实现方法
以上就是js中深拷贝与浅拷贝的详细介绍(代码分析)的详细内容。
