引用
JavaScript的一個重要的方面是引用的概念。引用就是指向對象實際位置的指標。這是一項極其強大的功能。前提是,實際的對象決不是一個引用:字串總是一個字串,數組總是一個數組。然而,多個變數可以引用相同的對象。JavaScript就是以這種引用引用機製為基礎。通過維護一系列的指向其它對象的引用,語言為你提供了更大的彈性。
另外,對象能包括一系列的屬性,這些屬性簡單地引用其它對象(如字串,數字,數組等等)。當幾個變數指向相同對象時,修改底層物件類型將會在所有的指點向它的變數上有所反映。例2-1即此一例,兩個變數指向同一個對象,但是對對象內容的修改的反映是全域的。
程式2-1. 多變數引用單個對象的樣本
//設定obj為一個Null 物件
var obj = new Object();
//objRef現在引用了別的對象
var objRef = obj;
//修改原始對象的屬性
obj.oneProperty = true;
//我們可以發現該變化在兩個變數中都可以看到
//(因為他們引用了同一個對象)
alert( obj.oneProperty === objRef.oneProperty );
我從前提到過自更改的對象在JavaScript裡非常少見的。讓我們看一個發生這一狀況的執行個體。數組對象能夠用push方法給它自己增加額外的項。因為在數組對象的核心,值是作為對象的屬性儲存區的,結果類似程式2-1中的情形,一個對象成為全域被改動的(導致了多個變數的值被同時改變)。見程式2-2.
程式2-2. 自修改對象的例子
//建立一組項目的數組
var items = new Array( "one", "two", "three" );
//建立一個對項目數組的引用
var itemsRef = items;
//給原始數組添加一項
items.push( "four" );
//兩個數組的長度應該相同,
//因為它們都指向相同的數組對象
alert( items.length == itemsRef.length );
記住這一點是很重要的:引用總是只指向最終被引用的對象,而不會是引用本身。例如,在Perl語言裡,很可能有一個引用指向另一個也是引用的變數。但在JavaScript裡,它會沿著引用鏈向下追溯直到指向核心的對象。程式2-3示範了這種情形,物理的目標已經改變而引用仍然指向原來的對象。
程式2-3. Changing the Reference of an Object While Maintaining Integrity(見#9 oerrite 的回複)
// 設定items為一個字串的數組(對象)
var items = new Array( "one", "two", "three" );
// 設定itemsRef為對items的引用
var itemsRef = items;
//讓items指向一個新的對象
items = new Array( "new", "array" );
// items和itemsRef現在指向不同的對象
// items指向new Array( "new", "array" )
// itemsRef則指向new Array( "one", "two", "three" )
alert( items !== itemsRef );
最後,讓我們來看一個陌生的例子,表面似乎是一個自修改的對象,卻作用於一個新的未被引用的對象。當執行字串串聯時,結果總是一個新的字串對象,而非原字串更改後的版本。這在程式2-4中可以看出。
程式2-4. 對象修改作用於一個新的對象而非自修改對象的樣本
//讓item等於一個新的字串對象
var item = "test";
//itemRef也引用相同的字串對象
var itemRef = item;
//在字串對象上串聯一個新的對象
//注意:這建立了一個新的對象,並不修改初始對象
item += "ing";
//item和itemRef的值並不相等,因為
//一個全新的對象被建立了
alert( item != itemRef );
如果你剛剛接觸,引用可能是個令人頭大的刁鑽話題。然而,理解引用是如何工作的對於編寫良好、乾淨的JavaScript代碼是極其重要的。接下來的幾節我們將探究幾種未必新鮮和令人激動的,但是同樣對編寫良好、乾淨的代碼很重要的特性。