搜了一些教程,归类整理

栈(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,导致地址指针是一样的,都同时指向堆里的同一个存储空间
JS堆与栈 拷贝

浅拷贝和深拷贝

浅拷贝的时候如果数据是基本数据类型,那么就如同直接赋值那种,会拷贝其本身,如果除了基本数据类型之外还有一层对象,那么对于浅拷贝而言就只能拷贝其引用,对象的改变会反应到拷贝对象上;但是深拷贝就会拷贝多层,即使是嵌套了对象,也会都拷贝出来。所以会有人粗略地说:浅拷贝是一层,深拷贝是多层。如果拷贝不彻底,改变新数组中嵌套的引用对象,原数据会改变。

浅拷贝

基本类型数据互不影响,虽然拷贝对象一开始新建,但浅拷贝里面的引用类型的地址指针是同一个

方法一

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)

JS堆与栈 拷贝
如果我们改变值呢

obj2.a=2
obj2.b=false
obj2.e=[4,5,6]
obj2.f.g=3
console.log(obj1,obj2)

JS堆与栈 拷贝
方法二

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

JS堆与栈 拷贝

方法三

递归

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);

JS堆与栈 拷贝

方法四

直接使用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堆与栈 拷贝

如有问题,欢迎斧正

相关文章:

  • 2021-11-01
  • 2022-02-02
  • 2021-10-20
  • 2021-07-09
  • 2022-12-23
  • 2021-09-27
  • 2021-12-20
猜你喜欢
  • 2021-08-12
  • 2022-01-06
  • 2021-05-17
  • 2021-10-03
相关资源
相似解决方案