八、JavaScript物件導向的支援
4. 執行個體和執行個體引用
在.NET Framework對CTS(Common Type System)約定“一切都是對象”,並分為“實值型別”和“參考型別”兩種。其中“實值型別”的對象在轉換成“參考型別”資料的過程中,需要進行一個“裝箱”和“拆箱”的過程。在JavaScript也有同樣的問題。我們看到的typeof關鍵字,返回以下六種資料類型:
"number"、"string"、"boolean"、"object"、"function" 和 "undefined"。我們也發現JavaScript的對象系統中,有String、Number、Function、Boolean這四種物件建構器。那麼,我們的問題是:如果有一個數字A,typeof(A)的結果,到底會是'number'呢,還是一個構造器指向function Number()的對象呢?
// 關於JavaScript的類型的測試代碼
function getTypeInfo(V) {
return (typeof V == 'object' ? 'Object, construct by '+V.constructor
: 'Value, type of '+typeof V);
}var A1 = 100;
var A2 = new Number(100);
document.writeln('A1 is ', getTypeInfo(A1), '<BR>');
document.writeln('A2 is ', getTypeInfo(A2), '<BR>');
document.writeln([A1.constructor === A2.constructor, A2.constructor === Number]);
測試代碼的執行結果如下:
A1 is Value, type of number
A2 is Object, construct by function Number() { [native code] }
true,true
我們注意到,A1和A2的構造器都指向Number.這意味著通過constructor屬性來識別對象,(有時)比typeof更加有效.因為"實值型別資料"A1作為一個對象來看待時,與A2有完全相同的特性.
--除了與執行個體引用有關的問題.
參考JScript手冊,我們對其它基礎類型和構造器做相同考察,可以發現:
- 基礎類型中的undefined、number、boolean和string,是“實值型別”變數
- 基礎類型中的array、function和object,是“參考型別”變數
- 使用new()方法構造出對象,是“參考型別”變數下面的代碼說明“實值型別”與“參考型別”之間的區別:
// 關於JavaScript類型系統中的值/引用問題
var str1 = 'abcdefgh', str2 = 'abcdefgh';
var obj1 = new String('abcdefgh'), obj2 = new String('abcdefgh');document.writeln([str1==str2, str1===str2], '<br>');
document.writeln([obj1==obj2, obj1===obj2]);
測試代碼的執行結果如下:
-----------
true, true
false, false
-----------
我們看到,無論是等值運算(==),還是全等運算(===),對"對象"和"值"的理解都是不一樣的.
更進一步的理解這種現象,我們知道:
- 運算結果為實值型別,或變數為實值型別時,等值(或全等)比較可以得到預想結果 - (即使包含相同的資料,)不同的對象執行個體之間是不等值(或全等)的 - 同一個對象的不同引用之間,是等值(==)且全等(===)的但對於String類型,有一點補充:根據JScript的描述,兩個字串比較時,只要有一個是實值型別,則按值比較.這意味著在上面的例子中,代碼"str1==obj1"會得到結果true.而全等(===)運算需要檢測變數類型的一致性,因此"str1===obj1"的結果返回false.
JavaScript中的函數參數總是傳入值參,參考型別(的執行個體)是作為指標值傳入的.因此函數可以隨意重寫入口變數,而不用擔心外部變數被修改.但是,需要留意傳入的參考型別的變數,因為對它方法調用和屬性讀寫可能會影響到執行個體本身.--但,也可以通過參考型別的參數來傳出資料.
最後補充說明一下,實值型別比較會逐位元組檢測對象執行個體中的資料,效率低但準確性高;而參考型別只檢測執行個體指標和資料類型,因此效率高而準確性低.如果你需要檢測兩個參考型別是否真的包含相同的資料,可能你需要嘗試把它轉換成"字串值"再來比較.