基本類型和引用類型的值
JavaScript 變量松散類型的本質(zhì),決定了它只是在特定時間用于保存特定值的一個名字而已。
變量的值及其數(shù)據(jù)類型可以在腳本的生命周期內(nèi)改變,這可能是一個既有趣又強大,同時又容易出問題的特性。
變量可能包含兩種不同數(shù)據(jù)類型的值:基本類型值和引用類型值
5個基本數(shù)據(jù)類型:Undefined、Null、Boolean、Number 和String
引用類型的值是保存在內(nèi)存中的對象,JavaScript 不允許直接訪問內(nèi)存中的位置,也就是說不能直接操作對象的內(nèi)存空間。
動態(tài)的屬性
對于引用類型的值,我們可以為其添加屬性和方法,也可以改變和刪除其屬性和方法:
var person = new Object();
person.name = "Nicholas";
alert(person.name); //"Nicholas"
但是,我們不能給基本類型的值添加屬性,盡管這樣做不會導致任何錯誤:
var name = "Nicholas";
name.age = 27;
alert(name.age); //undefined
這說明只能給引用類型值動態(tài)地添加屬性,以便將來使用。
復制變量值
基本類型的復制:會在變量對象上創(chuàng)建一個新值,然后把該值復制到為新變量分配的位置上:
var num1 = 5;
var num2 = num1;
在此,num1 中保存的值是5。當使用num1 的值來初始化num2 時,num2 中也保存了值5。但num2中的5 與num1 中的5 是完全獨立的,該值只是num1 中5 的一個副本。

當從一個變量向另一個變量復制引用類型的值時,同樣也會將存儲在變量對象中的值復制一份放到為新變量分配的空間中。不同的是,這個值的副本實際上是一個指針,而這個指針指向存儲在堆中的一個對象。
復制操作結(jié)束后,兩個變量實際上將引用同一個對象,改變其中一個變量,就會影響另一個變量。
var obj1 = new Object();
var obj2 = obj1;
obj1.name = "Nicholas";
alert(obj2.name); //"Nicholas"

傳遞參數(shù)
ECMAScript 中所有函數(shù)的參數(shù)都是按值傳遞的。也就是說,把函數(shù)外部的值復制給函數(shù)內(nèi)部的參數(shù),就和把值從一個變量復制到另一個變量一樣。
基本類型傳遞參數(shù):
function addTen(num) {
num += 10;
return num;
}
var count = 20;
var result = addTen(count);
alert(count); //20,沒有變化
alert(result); //30
在函數(shù)內(nèi)部,參數(shù)num 的值被加上了10,但這一變化不會影響函數(shù)外部的count 變量。
引用類型傳遞參數(shù):
function setName(obj) {
obj.name = "Nicholas";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
在這個函數(shù)內(nèi)部,obj 和person 引用的是同一個對象。換句話說,即使這個變量是按值傳遞的,obj 也會按引用來訪問同一個對象。于是,當在函數(shù)內(nèi)部為obj 添加name屬性后,函數(shù)外部的person 也將有所反映。
為了證明對象是按值傳遞的,我們再看一看下面這個經(jīng)過修改的例子:
function setName(obj) {
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
如果person 是按引用傳遞的,那么person 就會自動被修改為指向其name 屬性值為"Greg"的新對象。但是,當接下來再訪問person.name 時,顯示的值仍然是"Nicholas"。這說明即使在函數(shù)內(nèi)部修改了參數(shù)的值,但原始的引用仍然保持未變。
實際上,當在函數(shù)內(nèi)部重寫obj 時,這個變量引用的就是一個局部對象了。而這個局部對象會在函數(shù)執(zhí)行完畢后立即被銷毀。
檢測類型
為了知道變量是什么類型的對象,ECMAScript提供了instanceof 操作符,其語法如下所示:
result = variable instanceof constructor
如果變量是給定引用類型(根據(jù)它的原型鏈來識別;第6 章將介紹原型鏈)的實例,那么instanceof 操作符就會返回true。
alert(person instanceof Object); // 變量person 是Object 嗎?
alert(colors instanceof Array); // 變量colors 是Array 嗎?
alert(pattern instanceof RegExp); // 變量pattern 是RegExp 嗎?
根據(jù)規(guī)定,所有引用類型的值都是Object 的實例。因此,在檢測一個引用類型值和Object 構(gòu)造函數(shù)時,instanceof 操作符始終會返回true。當然,如果使用instanceof 操作符檢測基本類型的值,則該操作符始終會返回false,因為基本類型不是對象。