js语法深入二:js内存结构--数据与变量

在开发中,我们常常混淆数据和变量,其实这是两个相互关联单又不同的概念,想弄清这两个个概念我们还需要从js数据存储时的内存结构来看

  • 数据是什么? 变量是什么? 内存是什么?

    • 数据 :

      在编程语言中数据是存储在内存或硬盘中代表特定信息的。。。东西,它的本质是二进制编码;

      数据的特点是可存储,可修改;

      程序运行的本质是在内存中操作数据;

      我们常说一切皆对象,有它的道理但细究的话也不全面,对象实际上是数据的一种容器,或者说是一系列有关系的数据的集合。我觉的更准确的说法是一切皆数据。

    • 变量:

      • 可变化的量, 由变量名和变量值组成,在js中变量名是字符串类型的
      • 每个变量都对应的一块小内存, 变量名用来查找对应的内存, 变量值就是内存中保存的数据。
      • 变量的值不会是一个对象,引用变量保存的是对象数据的在堆内存中的地址
    • 内存

      • 内存条通电后产生的可储存数据的空间(临时的)
      • 内存产生和死亡: 内存条(电路版)==>通电==>产生内存空间==>存储数据==>处理数据==>断电==>内存空间和数据都消失
      • 一块小内存的2个数据
        • 内部存储的数据
        • 地址值
      • 内存分类
        • 栈: 存储变量
        • 堆: 存储对象
    • 数据 内存 和变量的关系

      • 内存用来存储数据的空间
      • 变量是内存的标识,js引擎根据这个表示找到并操作内存中的具体数据
    • 两个引用变量指向同一对象数据问题

      var obj1 = {a:1};
      var obj2 = obj1
      

      此时两个变量指向同一对象,让我们来用其中一个变量操作这个对象

      obj1.a = 2;
      console.log(obj2.a); //2
      

      结论一:2个引用变量指向同一个对象, 通过一个变量修改对象内部数据, 另一个变量看到的是修改之后的数据

      obj1 = {a:3};
      console.log(obj2.a); //2
      

      结论二:2个引用变量指向同一个对象, 让其中一个引用变量指向另一个对象, 另一引用变量依然指向前一个对象

      这两个结论看似简单,明了但我们很容易就在这上面栽跟头,让我们来看一个进阶应用

      可以自己先做一下
      
       var obj1 = {a:1};
       var obj2 = obj1;
      
      function fun(obj2) {
        obj2 = {a:2};
       }
        fun(obj2);
        console.log(obj2.a)
      

    结果是 1 ,先明确函数内外的obj2是两个不同的变量,在传参时外层obj2将他保存的对象地址传给了内层obj2,此时它们只想同一个对象。之后在函数内部对内层的obj2进行了重新赋值。根据“两个引用变量指向同一个对象, 让其中一个引用变量指向另一个对象, 另一引用变量依然指向前一个对象”,可以得出外层obj2依然执行原来的对象。

    • 传参问题

      上一个案例设计的参数传递问题,尤其是实参为变量时的参数传递,下面我们专门讨论下这个问题

      • 变量为基本变量: 此时的传递方式是值传递,也叫复制传递,变量做参数,传入的并不是变量本身,而是将变量的值复制一份赋给形参

        var a = 1;
        function fun (a){
        a = 2;
        }
        fun(a);
        console.log(a); //1;

        同样的内部和外部的a,是两个变量,传参是只是将外部a的值复制赋给内部的a,此后两者便没有关联。

      • 变量为引用类型的传递

        有人认为是值传递,有人认为是引用传递。其实都没错,只是说法不同。都是在说传递地址,前者的值说的变量保存的地址值,后者说的是对某一个对象数据的引用,其实说的是一件事。
        更为准确的描述:引用类型变量传递的是该变量中保存的对应对象的内存地址。在传参完成后实参和形参就是两个指向同一对象的变量。

    • 变量和数据的生命周期

      • 前置知识:

        • 1变量分局部变量和全局变量
        • 2变量占用栈内存空间
        • 3对象数据保存在堆内存中

        函数执行完(函数的执行上下文出栈)后,它的局部变量占用栈内存会被释放(不考虑闭包)

        全局变量占用的栈内存永远不会释放,引文全局的执行上下文始终在栈中(不会出栈)

        引用变量所指向的对象数据,当不存在变量指向它时,会被释放

        举一个简单但很能说明问题的例子

        function fun(){
            var a = {b:1}
        }
        fun();
        

        函数fun入栈—>栈内存开辟一块空间给a变量—>堆空间开辟一块空间给对象{b:1},并把这块空间的地址保存在a变量中—>**fun出栈—>**a占用的栈内存自动释放—>没有变量指向{b:1}对象,该对象占用的空间被回收

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值