《js高程》笔记总结二(变量,作用域,内存问题)

理解基本类型和引用类型的值,理解执行环境,理解垃圾收集

基本类型的值和引用类型的值

  • 基本类型:简单的数据段,引用类型:指可能由多个值构成的对象(在将一个值赋值的时候,解析器必须知道这个值是基本类型值还是引用类型值)
  • 复制变量值
    • 在基本类型中
      var num1=5;
      var num2=num1;
      
      其中num1和num2是完全独立的,各自都占用内存
    • 在引用类型中
      var obj1=new Object();
      var obj2=obj1;
      obj1.name="xiaoh"
      alert(obj2.name)  //xiaoh
      
      obj1和obj2知识拥有不同的索引值,但是他们都是指向同一个对象
  • 参数的传递
    • 可以把js中参数想象成一个局部变量
    • 当传递值基本类型的值时,被传递的值被复制了一份给局部变量(参数)
      function addTen(num){
        num+=10;
        return num;
      }
      var count=20;
      var result=addTen(count);
      alert(count);  //20 ,没有变化
      alert(result);  //30
      
    • 当传递引用类型的值时,会把这个值在内存中的地址复制一个给局部变量(参数)
      function serName(obj){
        obj.name="xiaoming"
      }
      var person = new Object();
      setName(person);
      alert(person.name);   //"xiaoming"  
      
      ==================================
      function setName(obj){  //此时obj只得到了索引
        obj.name = "xiaohuang";   // .属性 ,改变了对象的值
        obj=new Object();  //obj得到了新对象的索引,不再指向原来的对象
        obj.name ="greg" //改变的是索引指向的新对象的属性
      }
      var person=new Object();
      setName(person);
      console.log(person.name);  //小黄
      console.log(obj.name)
      

引用类型检测

  • 在检测数据类型的时候,typeof是非常得力的助手,但是引用类型的时候,我们经常并不是想知道他是不是对象,更多的想知道他是什么类型的对象。此时就有了instanceof操作符

    • alert(person instanceof Object) //变量person是Object吗
    • alert(colors instanceof Array) //同上
    • alert(pattern instanceof RegExp) //同上

执行环境及作用域

  • 执行环境:定义了变量或函数有权访问的其他数据,决定了他们各自的行为

  • 作用域:一段代码中的名字并不总是有效的,而限定这个名字的可用性代码范围就是这个名字的作用域。

    • 提高了程序的逻辑和局部性,为代码的模块化开发提供遍历
    • js代码中的作用域有哪些缺陷没有块级作用域for循环中定义的变量(i,j,a,b)可以被外部访问,所以js代码中for循环定义变量的时候都不写在for循环里面,还有if语句中{}声明的变量名也是一样
    • 我们可以使用函数作用域和自执行函数来模拟作用域
  • 作用域连

    • 保证变量在执行环境下的有序访问
    • var name = "global";
      function super() {
      var name = "super";
      function sub(){
           var name = "sub";
      }
      }
      
      当前作用域链:全局变量对象window -> 变量对象super —> 活动对象sub (从最底端向上访问)
  • 延长作用域链

    • 使用with语句

垃圾收集

  • 函数中的局部变量生命周期

    • 局部变量只在函数的执行过程中存在,在这个过程中。会为局部变量分配相应的空间,在函数结束,就释放他们的内存。
  • 标记清除

    • 进入环境的时候,标记"进入环境",离开环境的时候(如return)标记为"离开环境"
    • 释放内存的简单例子,var a =1; a=null;
    • 1.垃圾回收器会给内存中的变量都加上标记 2.去掉环境中的变量以及被环境中变量引用的变量的标记 3.在此之后在被加上标记的变量讲被视为准备删除的变量,原因是环境中的变量已经访问不到这些变量了(抽象例子 var a=1 ,var b=2 ,a=b)
  • 引用标记

  • 官话:当申明了一个变量并将一个引用类型赋值给该变量是,则这个的引用次数加1,如果同一个值又被赋给另一个变量,则该值的引用次数再加1,相反,如果包含对这个值引用的变量又取得了另一个值则减1,到0的话,就没有办法访问这个值了,则清除回收内存

  • 用伪代码案例来演示官方说明:

    var a = new obj1 (obj1引用1)
    var b=a (obj1引用2)
    b = c(c指其他值 ,obj1引用-1)
    a=  c( obj1引用-1)
    //此时obj1引用为0,已经没有变量能访问这个值了,则清除回收  
    
  • 引用标记的致命缺陷:循环引用,你的属性引用我,我的属性引用你。这样双方的引用次数都为2,永远不会被清除

管理内存

  • 使用具备垃圾回收机制的语言编写程序,开发人员一般不必操心内存管理的问题,但是,js有些不同,最主要的问题就是分配给web浏览器的可用内存数量通常比分配给桌面应用程序的少,这样做的目的主要出于安全考虑,防止运行js的网页耗尽全部系统内存而导致系统崩溃,内存问题不仅会影响给变量分配内存,同时还会影响调用栈以及在一个线程中能够同时执行的语句数量
  • 优化内存占用的最佳方式就是,代码中只保存必要的数据,一旦数据不再用就将其值设置成null来释放内存,这个叫解除引用,大多数适用于全局变量和全局对象的属性,局部变量会在他们离开执行环境时自动被解除引用。

总结

  • 每次进入一个新的执行环境,都会创建一个用于搜索变量和函数的作用域链(只能从下往上访问),函数的局部变量(下端)不仅有权访问函数作用域中的变量,还能访问其父环境,乃至全局环境,而全局环境(上端)只能访问全局环境中定义的变量和函数。
原文地址:https://www.cnblogs.com/JCDXH/p/11609866.html