JS 赋值、浅复制、深复制 和堆栈的理解

404 阅读2分钟

1. 数据类型

  • 基本类型:Number、String、Boolean、Null、Undefind、Symbol、BigInt。
  • 引用类型:Objetc、Function、Array、Date

2.栈和堆的理解

  • 栈是自动分配相对固定大小的内存空间,并由系统自动释放。
  • 堆是动态分配内存,内存大小不一,也不会自动释放。
  1. 栈内存:存储基本类型值和指定代码的环境。
  2. 堆内存:存储引用类型值的空间。

3.基本类型

基本类型值,在赋值、浅拷贝、深拷贝时都是复制基本类型的值给新的变量,之后二个变量之间操作不在相互影响,在两个不栈内存中。

let a = 10; 
let b = a; 
b = 11; 
console.log(a); 
//10 
console.log(b); 
//11

image.png

4.引用类型

引用类型的值是同时保存在栈内存和堆内存中。 image.png 4.1 赋值,两个变量指向同一个地址,一个变量值改变时,另一个同样改变。

let c = {name:"学习数据类型"};
let d = c; //其实只是c变量的内存地址赋值给d变量
console.log(c,d); 
//{name: '学习数据类型'} {name: '学习数据类型'}

d.name = "学会了";
console.log(c,d)  
//{name: '学会了'} {name: '学会了'}

image.png

4.2 浅拷贝,得到一个新的变量,这个对象有着原始对象属性值的一份精确拷贝。

  • 如果属性是基本类型,拷贝的就是基本类型的值。
  • 如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
let e = { name:"小明",child: { interest: "篮球"}};
let f = {...e}; //通过解构浅拷贝
f.name = "小黄"; // 修改基本类型互不影响
f.child.interest = "足球"; //修改child对象,引用类型会影响
console.log(e,f);

image.png
常用的浅拷贝有:数组slice、concat、Array.from(), Object.assign({},obj)。

4.3 深拷贝,得到一个全新变量,它的改变不会影响原对象。 使用基础版实现深拷贝 JSON.parse(JSON.stringify(obj));
Symbol、Function、undefined、正则、 Date 不起效果

let obj1 = {name:"学习引用类型"};
let obj2 = JSON.parse(JSON.stringify(obj1));

image.png

使用递归实现对象深拷贝

let obj = {
  a: 1,
  b: "学习深拷贝",
  c: function(){},
  d: /\d/,
  e: new Date(),
  f: { dd: 12},
  g: Symbol(1),
  h: undefined,
  i: [1,2,{ c: 3 }]
}
function  deepClone(obj){ 
 if(obj === nullreturn null//因为typeof(null)也是Object     
 if(typeof(obj) !== "object"){ //非Object类型直接返回         
   return obj;     
 }     
 if(obj instanceof RegExp){ 
   return new RegExp(obj);  //返回新的正则  
  }     
  if(obj instanceof Date){         
   return new Date(obj);   //返回Date     
  }     
  if(obj instanceof Function){         
   return new Function(obj) //返回函数     
  }     
  if(obj instanceof Symbol){         
   return new Symbol(obj) //返回Symbol     
  }     
  let newObj = new obj.constructor;     
  for(let key in obj){         
      if(obj.hasOwnProperty(key)){             
          newObj[key] = this.deepClone(obj[key])        
      }     
  }     
   return newObj; 
  }
  let deepCopyObj = deepClone(obj);
  console.log(deepCopyObj)

image.png