数据类型与堆栈内存关系

371 阅读2分钟

概述

通过学习堆栈内存关系引发的一系列思考,对此进行知识总结。

案例一:基础类型复制

let a = 1 // 创建一个栈内存空间
b = a // 赋值a的栈内存空间
b = 2 // 创建一个新的栈内存空间
console.log(a)
console.log(b)

结果:
1
2

image.png

案例二:引用类型复制

let a = {name: 'weili', age: '18'} // 创建一个对象,地址存储在栈中,内容在堆中新创建一个内存空间存放
b = a // 赋值a引用内存的地址
b = {name: 'xiaoye', age: '20'} // 新建一个对象,另起一个地址与堆存储空间
c = a//  赋值a引用内存的地址
c.name = 'xiaohong' // 修改a引用内存地址中堆的数据内容,c地址没变,依旧指向a
console.log(a)
console.log(b)
console.log(c)

结果:
{ name: 'xiaohong', age: '18' }
{ name: 'xiaoye', age: '20' }
{ name: 'xiaohong', age: '18' }

image.png

案例三:浅拷贝

let a = {name: 'weili', age: '18',student:{'number':1}} // 创建一个对象
let b = Object.assign({}, a) // 浅拷贝一个对象,只新创建了第一层对象地址指向,只对第一层数据新建内存空间
b.age = 20 // 修改b中内存空间数据,只有b内容才会受影响
b.student.number = 2 // 修改b中number数据,由于a与b指向一个内存空间,所以两边都会发生变化
console.log(a)
console.log(b)
结果:
{ name: 'weili', age: '18', student: { number: 2 } }
{ name: 'weili', age: 20, student: { number: 2 } }

image.png

案例四:深拷贝

/**
 * 简单版深拷贝
 */
function deepClone(obj) {
  // 如果obj类型不是引用类型则直接返回数值
  if(typeof obj !== "object") {
    return obj
  }
  // 判断对象类型
  var objClone = Array.isArray(obj) ? [] : {};
  // 遍历对象内容
  for(key in obj) {
    // 判断obj是否有属性key
    if(obj.hasOwnProperty(key)) {
      // typeof null 为object,所以需要判断obj[key]
      if(obj[key] && typeof obj === "object") {
        // 递归深入查找对象
        objClone[key] = deepClone(obj[key])
      } else {
        objClone[key] = obj[key]
      } 
    }
  }
  return objClone
}

let a = {name: 'weili', age: '18',student:{'number':1},arr:[1,2,3]} 
let b = deepClone(a) // 主要是将所有的堆内存空间复制一份,防止数据互相影响
b.age = 20
b.student.number = 2
b.arr[0] = 4
console.log(a)
console.log(b)

结果:
{ name: 'weili', age: '18', student: { number: 1 }, arr: [ 1, 2, 3 ] }
{ name: 'weili', age: 20, student: { number: 2 }, arr: [ 4, 2, 3 ] }