以下大部分为学习《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>