js 深拷贝 vs 浅拷贝

js 深拷贝 vs 浅拷贝

js的数据基本类型有

string, number, boolean, undefined, null

引用类型有

object, function

js的v8引擎主要由两部分组成

  • 内存堆(Memory Heap) -- 分配地址的地方
  • 执行栈(Call Stack) -- 执行代码的地方

基本数据类型存放在 栈 中,是直接按值存放的,可以直接访问。

基础类型的值是不可变的, 就算动态改变了其值,返回新的值,但它的原始值是不会变的

var a = '123'
a[0] = '4'
console.log(a) // 123 

所以记住,基础类型数据的值是不可变的。

而且基础类型的比较,是值的比较,只要值相等就是相等

var a = 1
var b = 1
console.log(a === b) //true 

引用类型(object/function)是放在 堆 中的。

变量其实是一个放在栈中的指针,指针指向堆内存中的地址。

var person1 = {a: 1}
var person2 = {a: 2}
var person3 = {a: 3} 

引用类型是可以直接改变其值的

var a = {b: 1}
a['b'] = 2
console.log(a)  //{b: 2}

引用类型的比较是引用的比较,也就是指针地址的比较

var a = {c: 1}
var b = {c: 1}
console.log(a == b) //false
console.log(a===b) //false

数据赋值区别

基本类型的赋值是两个独立互不影响的变量。

var a = 1
var b = a
a = 2
console.log(a)  //2
console.log(b) //1

引用类型的赋值,实际上是传址,改变指针的指向。

也就是两个不同的栈指向相同的堆地址,变化会互相影响

var a = {}
var b = a 
a.name = 1
console.log(a)  // {name: 1}
console.log(b) // {name: 1}
console.log(a == b) //true 

但是,以上这种赋值并不算浅复制,只能算是引用。

对于基本类型,浅复制就是对值的赋值,

对于引用类型,浅复制是对对象地址的赋值,并在堆中没有开辟新的地址。

而深复制会开辟新的地址,两个对象指向不同地址,互不影响。

这边我们只讲深复制,浅复制比较简单不做代码演示。

深拷贝

//方法一:有局限性,嵌套obj无法复制
var ary2 = ary1.concat();

//方法二:有局限性,会丢失function
var ary2 = JSON.parse(JSON.stringify(ary1));

//方法三, 有局限性,嵌套obj无法复制
var ary2 = [...ary1];

// 方法四, 有局限性,嵌套obj无法复制
var [...ary2] = ary1;

// 方法五,递归拷贝,推荐!!!
// 所有继承了 Object 的对象都会继承到 hasOwnProperty 方法,这个方法可以用来检测一个对象是否含有特定的自身属性;
// 和 in 运算符不同,该方法会忽略掉那些从原型链上继承到的属性。

function deepClone(obj) {
  let copy = obj instanceof Array ? [] : {}
  for (let i in obj) {
    if (obj.hasOwnProperty(i)) {
      copy[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
    }
  }
  return copy
}

原文地址:https://www.cnblogs.com/hustshu/p/14864335.html