JS高级类型存储方式——含堆/栈分析

1、内存

  • 在编写正式内容前,首先需要弄清楚的一个概念就是:内存
  1. 内存 :也就是电脑中的硬件内存越大,可以同时开启的程序就越多
  2. 内存的作用
    • 存储运行中的代码,把代码执行过程中所需要的数据,都放在内存中,进行临时的存储
    • 程序关闭时,在从内存中取出这些数据,所有的变量在程序运行的过程中都是放在内存中进行存储的

2、堆/栈概念

2.1、栈

  • 概念:
    • 是一种数据结构,遵循后进先出(LIFO,Last In First Out)的原则。
    • 也就是:最先入栈的数据最后出栈,而最后入栈的数据最先出栈。
  • 栈中的数据结构
    • 中,通常存储函数调用时的局部变量、参数和返回地址
    • 中的每个元素可能包括变量实际值对象的引用地址

2.2、堆

  • 概念:
    • 是一种用于动态分配内存内存区域
    • 程序运行时,可以在中申请所需的内存,并在使用完毕后手动释放。
  • 堆中的数据结构
    • 栈中的指针:保存指向堆中数据的内存地址。
    • 堆中的值:实际存储在堆中的数据,如对象的属性或数组的元素。

2.3、注意

  1. 我们在存储高级类型变量中,存储的并不是高级类型的值,而是高级类型的地址
    • 比如:在里存储了arr数组,那么跟它一起存放的并不是对应的数据,而是对应数据存储的地址
    • 这个地址的对应的位置是,把数据放在了里,并给它取一个"名字"也就是地址,方便获取地址
  2. 堆/栈的存储模型不是一样的

3、高级类型存储的特征

// 示例1:
          var arr1 = [];
          var arr2 = [];
    // 1)比对时,结果为false
    // 2)因为在栈里的变量,存的是地址,而不是它的值,此时比较的是两个数组的存储地址,地址当然是不一样的,所以是false
          console.log( arr1 === arr2 ); 

// 示例2:共用地址 => 高级类型可以多个变量共用一个地址:创建1个数组,好多个变量都用这个数组的地址
      var arr3 = []; 
    // 1)arr3和arr4共用一个数组的地址,但这种操作其实并不好,会产生一些意外的结构,此时操作arr4地址对应的数组,arr3查看的是同样的数组
      var arr4 = arr3;  
    // 2)再后方添加数据
      arr4[arr4.length] = "hello world"; 
    // 3)输出成功,arr3里也增加了"hello world"
      console.log( arr3 ); 
    // 4)注意:
        // 同级别尽量规避这样的同地址变量使用,只在作用域不同的情况下使用这种地址赋值
        // 比如上面的示例,可以直接访问arr3,就没什么必要额外再去增加一个变量arr4,再进行操作

// 示例3:特殊情况共用地址
      function push( arr , data ){  
    // 1)通过push函数向数组最后面添加了一条数据
           return arr[ arr.length ] = data; 
      }
        var arr5 = []; 
    // 2)在调用函数时,实参必须是数据,如果实参位置是变量则表示变量访问 => 此时的arr5就是数组的地址,"hello world5"就是对应的data
        push( arr5 , "hello world5" ); 
        console.log( arr5 );
                             
        var arr6 = [];
    // 3)这里同上
        push( arr6 , "你好世界") 
        console.log( arr6 );
    // 4)解释:通过调用push函数可以给当前数组的最后位置添加一条数据,这里使用了共用地址

4、补充示例

// 1、修改obj2中的name会影响到obj1,且obj1赋值给obj2时打印两者是否相等 => true
// 解释: 
      // 1)因为:obj1被赋值给了obj2 => 其实是把obj1的地址复制给了obj2,那么当obj2修改数据的时候,会访问到obj1内容的"本尊",则修改数据时,会导致obj1也被修改
      // 2)通俗点解释就是:去酒店住宿,同一间房给了两张房卡,使用a卡进去后,拿出来一件东西,在使用b卡进去时,东西是必然少了的
      var obj1 = {
        name : "吴彦祖",
        age : 18,
        location : "北京"
      }
      var obj2 = obj1
      console.log(obj1 === obj2); // true
      obj2.name = "刘德华"
      console.log(obj1,obj2); // 数据相等

// 2、两个一模一样的对象,对比结果是不相等的
// 解释:
      // 虽然看着一模一样,但是两个对象的地址是不一样的,obj3在堆里存放完数据后给栈里的返回的是1个地址,而obj4存放完后再返回的则是另外一个地址了
     var obj3 = {name : "刘亦菲"}; 
     var obj4 = {name : "刘亦菲"};
     console.log(obj3 === obj4); // false

// 3、正确复制对象的方法
   // 1)声明空对象
     var obj5 = {} 
     var obj6 = {
         name : "张韶涵",
         age : 22,
         location : "北京"
     };  
   // 2)遍历obj6中的每一项数据
     for(var i in obj6){  // 
   // 3)取出obj6中每项数据后,再复制给obj5 => 此时两个对象的存储地址就不一样了,和直接复制是不同的,这里是一个对象一个地址,不存在一个房间两张房卡的情况              
        obj5[i] = obj6[i] 
     }
  // 4)修改添加后的name值
     obj5.name = "迪丽热巴" 
  // 5)可以正确修改,不会影响obj6的数据
     console.log(obj5,obj6);
</script>

5、堆/栈简易示例图

在这里插入图片描述

  • 14
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值