一、变量分类:
基本类型值:null、undefined、number、string、Boolean;
引用类型值:保存在内存中的对象,如:Object / Array / Function / Date / RegExp / Error / Map / Set …
二、属性
二者的定义方式是类似的:创建一个变量并为其赋值。
2.1基本类型值不能添加删除属性
2.2引用类型的属性可以动态添加删除属性
例如:
1 <script type="text/javascript"> 2 var person = new Object(); 3 person.name = "Nicholas"; 4 alert(person.name); //"Nicholas" 5 </script>
上述例子创建了一个对象并将其保存在变量person中,然后我们又为这个对象添加了一个name属性,并将一个字符串赋值给该属性。
再看一个例子:
1 <script type="text/javascript"> 2 var name = "Nicholas"; 3 name.age = 27; 4 alert(name.age); //undefined 5 </script>
可见基本类型的值是不能动态添加属性的,尽管不报错。
三、复制变量值
3.1基本类型值复制变量
同样通过代码来说明:
var num1=2; var num2=num1;
变量num2只是把num1中存储的值(2)复制了一份,然后保存在自己的内存空间,此后这两个变量可以参与任何操作而互不影响。
3.2引用类型值复制变量
var obj1= new Object(); var obj2=obj1; obj1.name="jack"; alert(obj2.name);//jack
同样的,obj2也是把obj1中存储的值复制了一份,然后保存在自己的内存空间,只不过这个值实际上是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上将引用同一个对象。两个变量其实是相互同步的。
四、传递参数
ECMAscript中所有函数的参数都是按值传递的:把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。
4.1基本类型的值
被传递的值会被复制给一个局部变量(也就是命名参数:形参,也就是arguments对象中的一个元素)。见http://www.cnblogs.com/yxField/p/4224380.html中所提到的。
需要说明的是:String一个特殊的基本数据类型
在很多语言中,String是以对象的形式表示的,但在ECMAScript里没有沿用这种传统,String是当作一种基本数据类型,但它是一个比较特殊的基本类型。
看上去好像String应该做为一个引用类型,可实际上它不是,因为它不是对象。那么看起来它应该是基本数据类型,应该是通值传递的方式来操作。
看下面例子:
var stra = "这是一个字符串"; var strb = stra; stra = "这是另外一个字符串"; console.log(strb); // 这是一个字符串
上面例子我们看到,仿佛stra通过值传递的方式复制了一份给了strb。当stra改变的时候,strb并没有改变,似乎我们已经可以下结论,String就是个基本数据类型。
可是,因为String是可以任意长度的,通过值传递,一个一个的复制字节显示效率依然很低,看起来String也可以当作引用类型。
看下面例子:
var a = "myobject"; a.name = "myname"; console.log(a.name); // undefined
显示String无法当作一个对象来处理。实际上,javascript里的String是不可以改变的,javascript也没有提供任何一个改变字符串的方法和语法。
var a = "myobject"; a = a.substring(3,5) console.log(a); // bj
记住这样做,就没有改变String字符串"myobject",只a引用了另一个字符串"bj","myobject"被回收了。
所以可以这样讲,String实际上并不符合上面两种数据类型分类。它是具有两方面属性介于两都之间的一种特殊类型。
4.2引用类型的值
在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反应在函数的外部。
例如:
1 <script type="text/javascript"> 2 function setName(obj) { 3 obj.name = "Nicholas"; 4 } 5 6 var person = new Object(); 7 setName(person); 8 alert(person.name); //"Nicholas" 9 10 </script>
上述例子中,变量person在复制给obj时,把它所保存的对象在内存中的地址复制给了obj,所以obj和person引用的还是同一个对象。
为了证明对象是按值传递的,再看个例子:
1 function setName(obj) { 2 obj.name = "Nicholas"; 3 obj=new Object(); 4 obj.name="jack"; 5 } 6 7 var person = new Object(); 8 setName(person); 9 alert(person.name); //"Nicholas"
上述例子中,如果person是按引用传递的,那么person.name就会变成Jack,这说明即使在函数内部修改了参数的值,但是原始的引用仍然保持不变。实际上,当函数内部重新写obj时,这个变量引用的就是一个局部对象了,这个局部对象会在函数执行完之后被立即销毁。
五、检测类型
5.1检测基本数据类型:typeof
见http://www.cnblogs.com/yxField/p/4211704.html
5.2检测引用类型值:instanceof
例如:
1 var s =[1,2]; 2 var a = true; 3 var i = new Object(); 4 5 6 alert(i instanceof Object); //true 7 alert(a instanceof Object); //false 8 alert(s instanceof Array); //true