• JavaScript 【变量、作用域和内存问题】基本类型和引用类型的值


    以下大部分为学习《JavaScript 高级程序设计》》(第 3 版) 所做笔记。

    目录:

    1、动态的属性

    2、复制变量值

    3、传递参数

    4、检测类型

    ES 变量可能包含 2 种不同数据类型的值:基本类型值引用类型值

    基本类型值(也叫简单数据类型)指的是简单的数据段。Undefined、Null、Boolean、Number 和 String 都是基本类型,它们是按值访问的,保存在中。

    引用类型值是保存在内存中的对象。Object 是引用类型,是按引用访问的。保存在中。JS不允许直接访问内存中的位置,在操作对象时,实际上是操作对象的引用而不是实际的对象。

    动态的属性

     对于引用类型值,我们可以为其添加属性和方法,也可以改变其属性和方法。对于基本类型值,我们不能给其添加属性,尽管这样不会导致错误。

     1 <script>
     2     //引用类型的值
     3     var a = new Object();
     4     a.name = "xiaoxu";
     5     console.log( a.name );      //输出:xiaoxu
     6     //基本类型的值
     7     var b = "nana";
     8     b.age = 22;
     9     console.log( b.age );       //输出:undefined
    10 </script>

    复制变量值

    ① 基本类型值的复制

     1 <script>
     2     //num1 保存的值是 5
     3     var num1 = 5;
     4     //num2 保存了 5的一个副本,变量 num1 跟 num2 相互独立、互不影响
     5     var num2 = num1;
     6     console.log( num1 );    //输出:5
     7     console.log( num2 );    //输出:5
     8     num2 = 12;
     9     console.log( num1 );    //输出:5
    10     console.log( num2 );    //输出:12
    11 </script>

     

    ②引用类型值的复制

    1 <script>
    2     var obj1 = new Object();
    3     //一个变量向另一个变量复制引用类型的值,这个值是一个指针,指针指向存储在堆中的一个对象
    4     var obj2 = obj1;
    5     //两个变量将引用同一个对象,改变其中一个变量,会影响另一个变量
    6     obj.name = "xiaoxu";
    7     console.log( obj2.name );
    8 </script>

    传递参数

    参数只能按值传递。 基本类型值的传递如同基本类型值的复制一样,引用类型值的传递如同引用类型变量的复制一样。

    ① 向参数传递基本类型的值

    在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数,或者用 ES 的概念来说,就是 arguments 对象的一个元素)。

     1 <script>
     2     //函数的参数实际上是函数的局部变量
     3     function addTen( num ){
     4         num += 10;
     5         return num;
     6     }
     7     var count = 20;
     8     //调用函数,变量 count 作为参数被传递给函数,数值20被复制给 num
     9     //参数按值传递,所以 count 跟 num 相互独立互不影响
    10     //可以看到 num 在函数内部进行运算后变成了 30, 但是函数外部的 count 仍为20,说明了它们的确是按值传递的
    11     var result = addTen( count );
    12     console.log( count );   //输出:20
    13     console.log( result );  //输出:30
    14 </script>

    ②向参数传递引用类型的值

    在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部。

     1 <script>setName
     2     function setName( obj ){
     3         obj.name = "xiaoxu";
     4         //重写 obj ,变量 obj 这是引用的是一个局部对象,这个局部对象会在函数执行完毕立即销毁
     5         obj = new Object();
     6         obj.name = "mona";
     7     }
     8     var person = new Object();
     9     setName( person );
    10     console.log( person.name );     //输出:xiaoxu
    11 </script>

    说明:

      根据我的理解,将变量 person 传递给 setName() 函数之后被复制给了 obj, 变量值是 person 指向的对象的内存地址。每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。函数 setName() 执行到 obj.name = "xiaoxu"之后,内存地址2中的对象的变量 name 的值为 “xiaoxu”,此时访问 person.name ,显示的值为 “xiaoxu”。在执行到语句 obj = new Object(); 之前的内存如下:

    执行到语句 obj = new Object() 之后,相当于重写了 obj,obj 引用的就是一个局部对象了。此时访问 person.name ,显示的值仍然为 “xiaoxu”。

     在函数执行完之后,栈将其环境弹出,把控制权返回给之前的执行环境。obj 引用的局部对象会在函数执行完毕之后立即销毁。

    检测类型

       typeof 操作符在检测基本数据类型的值时用处比较大,在检测引用数据类型的值时用处不大。

     1 <script>
     2     var a = "a";
     3     var b = 0;
     4     var c = true;
     5     var d;
     6     var e = null;
     7     var f = new Object();
     8     function g(){};
     9     var h = new Array();
    10     var pattern1 = /at/g;
    11     //基本类型值
    12     console.log( typeof a );    //输出:string
    13     console.log( typeof b );    //输出:number
    14     console.log( typeof c );    //输出:boolean
    15     //undefined、null
    16     console.log( typeof d );    //输出:undefined
    17     console.log( typeof e );    //输出:object
    18     //引用类型值
    19     console.log( typeof f );        //输出:object
    20     console.log( typeof g );        //输出:function
    21     console.log( typeof h );        //输出:object
    22     console.log( typeof pattern1 ); //输出:object
    23 </script>

      所有引用类型的值都是 Object 的实例,因此在检测一个引用类型值和 Object 构造函数时,instanceof 操作符始终会返回 true。

     1 <script>
     2     var a = "a";
     3     var b = 0;
     4     var c = true;
     5     var d;
     6     var e = null;
     7     var f = new Object();
     8     function g(){};
     9     var h = new Array();
    10     var pattern1 = /at/g;
    11     //基本类型值
    12     console.log( a instanceof Object );    //输出:false
    13     console.log( b instanceof Object );    //输出:false
    14     console.log( c instanceof Object );    //输出:false
    15     //undefined、null
    16     console.log( d instanceof Object );    //输出:false
    17     console.log( e instanceof Object );    //输出:false
    18     //引用类型值
    19     console.log( f instanceof Object );            //输出:true
    20     console.log( g instanceof Object );            //输出:true
    21     console.log( h instanceof Object );            //输出:true
    22     console.log( pattern1 instanceof Object );     //输出:true
    23     console.log( g instanceof Function );          //输出:true
    24     console.log( h instanceof Array );             //输出:true
    25     console.log( pattern1 instanceof RegExp );     //输出:true
    26 </script>

      如果变量是给定引用类型的实例(根据它的原型链来识别),那 instanceof 操作符会返回 true。

     1 <script>
     2     function a(){};
     3     function b(){};
     4     //b 继承了 a
     5     b.prototype = new a();
     6     var instance = new b();
     7     console.log( instance instanceof a );       //true
     8     console.log( instance instanceof b );       //true
     9     //所有函数的默认原型都是 Object 的实例
    10     console.log( instance instanceof Object );  //true
    11 </script>
  • 相关阅读:
    angularJS中的MVC思想?
    angularJs初体验,实现双向数据绑定!使用体会:比较爽
    原生JS去解析地址栏的链接?超好用的解决办法
    HDCMS多图字段的使用?
    sublime添加到鼠标右键打开文件的方法?
    Ajax做列表无限加载和Ajax做二级下拉选项
    Atitit.获取某个服务 网络邻居列表 解决方案
    Atitit. 注册表操作查询 修改 api与工具总结 java c# php js python 病毒木马的原理
    Atitit. 注册表操作查询 修改 api与工具总结 java c# php js python 病毒木马的原理
    Atitit.prototype-base class-based  基于“类” vs 基于“原型”
  • 原文地址:https://www.cnblogs.com/xiaoxuStudy/p/12509729.html
Copyright © 2020-2023  润新知