JS中的栈内存和堆内存

109 阅读2分钟

JS中有两大数据类型

  • 基本数据类型(Number、String、boolean、null、undefine、Symbol、BigInt)
  • 引用数据类型(Array、Function、Object)

基本数据类型是存放在栈内存中的,因为基本数据类型,占的空间小,值固定,按值来访问。

引用数据类型存放在堆内存中,因为引用数据类型占据空间大、大小不固定。引用数据类型,存放在栈内存中的是一个地址。

数据的存放形式如图: uTools_1690774257073.png

变量的复制

当我们的去拷贝一个变量的时候,如果该变量是一个基本数据类型,那我们拷贝的是一个值;如果该变量是一个引用数据类型,那我们拷贝的是一个地址。

uTools_1690777485587.png

如图,我们拷贝了一个对象,拷贝是这个对象的地址,而不是这个对象本身,当我们去修改了,attribute.a的值,对应的copyAttribute.a的值,也会变成修改的值。

深拷贝的实现

1.JSON的序列化和反序列化可以实现深拷贝

const obj = {a: 1, b: 1}
const copyObj = JSON.parse(JSON.stringify(obj))

2.递归实现深拷贝

function deepClone(source) {
    // 1.建立一个新容器
    let targetObj = Array.isArray(source) ? [] : {}
    
    // 2.遍历
    for(let key in source) {
        if(source.hasOwnProperty(key) {
            // 3.处理数据类型
            if(source[key] &&  typeof source[key] === 'object') {
                targetObj[key] = deepClone(source[key])
            } else {
                targetObj[key] = source[key]
            }
        }
    }
    return targetObj
}

为什么const定义的数组和对象是可以改变的?

const定义的数组和对象,在栈内存中,存储的是一个地址,当改变数组和对象的时候,地址是并没有被改变的,const定义的还是一个常量,所以const定义的数组和对象是可以改变的。

为什么let和const不能重复定义?

当去定义let和const的时候,会去遍历整个栈内存,如果发现相同的遍历,直接抛出错误。