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

时间:2020-03-24
本文章向大家介绍JavaScript 【变量、作用域和内存问题】基本类型和引用类型的值,主要包括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>

原文地址:https://www.cnblogs.com/xiaoxuStudy/p/12509729.html