JavaScript高级程序设计(第3版)笔记(四)

来源:互联网 发布:水果网络营销策划方案 编辑:程序博客网 时间:2024/05/01 06:44
第四章 变量、作用域和内存问题
    4.1  1.操作对象,实际是操作对象的引用,即引用类型的值是按引用访问的。引用类型值可以动态增删改属性和方                法,而基本类型值不可以
              当从一个变量向一个变量中复制引用型值时,实际上是引用的指针,一个变量发生变化会影响到另一个变量

              访问变量的两种方式:按值(基本类型),按引用(引用类型)访问

              var name = 'lily';
              name.age = 12;
              console.log(name.age);//undefined 

              注:为变量添加属性虽然不报错,但是无效 只有引用类型可以动态添加属性

           2.函数中的参数是按值传递的,基本类型作为参数传递时,相当于在函数内部复制生成了局部变量,两个变量                互不影响;引用类型作为参数传递时,相当于在函数内部进行了复制,实际上引用的还是同一对象,因此                  两变量互相影响
           3.检测引用类型的值  
             a instanceof Object      a是否为Object
             a instanceof Array       a是否为Array
             a instanceof RegExp      a是否为RegExp

             注:(1)typeof检测函数时返回function

                    (2)引用类型的值都是Object的实例

                    (3)除了基本类型以外,都是引用类型

                      var a = []; 
                      a instanceof Array;   //true  
                      a instanceof Object;  //true  
    4.2  执行环境及作用域
           执行环境决定变量或函数是否有权限访问其他数据,每个执行环境都有与之关联的变量对象。环境中定义的               变量和函数都保存在这个对象中,当执行环境中的代码都执行完之后,执行环境将销毁,其中的变量与函数               也随之销毁。当代码在一个环境中执行时,会创建变量对象的一个作用域链,作用域链用来保证有权访问的               变量和函数的顺序,作用域的前端为当前执行环境中的变量对象,不断向外部执行环境延伸
         1.延长作用域链                              在作用域前端添加变量对象
             try-catch语句的catch块            会创建一个变量对象,添加到作用域
             with语句                                   with会将指定的对象添加到作用域

         2.没有块级作用域 (if,for等)    注:严格模式下,对未声明的变量赋值,会报错

    4.3  管理内存
           不使用的对象,可赋值为null,手动接触引用,让值脱离执行环境,以便垃圾收集器下次运行时将其回收

疑问:1.为什么对象在函数中的传递是按值传递?
            变量分为基本类型和引用类型(即对象)。
            基本类型,因为占用的内存固定,而且不大直接存储在栈中。
            引用类型,占用的内存无法固定,同时占据的内存可能很大,所以存储在堆中,而在栈中存储的只是指向堆              的地址,因此在复制时,基本类型直接将数据进行复制,而引用类型只是复制了栈中的地址。
            在函数传递参数的过程中可以理解为复制变量,有以上复制基本类型的原理可以知道,实参与形参在复制时              候将各自独立;而引用类型是将地址进行复制,所以在函数内,对对象的属性进行改变时,会影响到外部。              但是当函数中的新对象赋值给参数时,参数的地址发生了变化,与实参的地址不在相同,因此不会对彼此影              响。可见对象的传递是按值传递,若是按引用传递,当形参地址发生变化时,实参的地址也应该跟着改变。
            var obj1 = {value: '222'};
            var obj2 = {value: '333'};
            function changeValue(obj){
      obj.value = '444';   //obj与obj1指向同一地址,value发生变化将会影响obj1
              obj = obj2;            //obj地址发生变化,与obj1将不存在关联,不再影响obj1
              return obj.value; 
    }
            var newValue = changeValue(obj1);
            console.log(obj1.value);            //'444'
            console.log(newValue);             //'333'

            借鉴于:https://www.zhihu.com/question/27114726
          2.catch,with如何延长作用域链?
            (1)在一个函数中,在try中的语句出现错误时,执行过程会调到catch中,创建个可变对象(error错误对                         象),会放在函数作用域的前端,从而延长了作用域链。函数中所有的变量将变成保存在第二作用域                         象中,当catch中引用函数中的变量时,变量需要访问第二作用域,相比使用catch之前访问当前作用                         域,影响了性能。不过由于try-catch在异常处理时很有作用,可以不用避免
            (2)with与catch原理类似,运行with语句时,会创建一个新的可变对象,参数对象保存在新的可变对象                           中,可变对象会放在函数作用域的前端,从而延长了作用域链。可能会产生性能问题,尽量避免使                             用。可以通过定义一个统一的变量,引用变量达到with语句的目的。
                     借鉴于:https://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html

阅读全文
0 0