ECMAScript 引用類型

引用類型一般叫作類(class)。java

本教程會討論大量的 ECMAScript 預約義引用類型。安全

引用類型

引用類型一般叫作類(class),也就是說,遇到引用值,所處理的就是對象。函數

本教程會討論大量的 ECMAScript 預約義引用類型。編碼

從如今起,將重點討論與已經討論過的原始類型緊密相關的引用類型。設計

注意:從傳統意義上來講,ECMAScript 並不真正具備類。事實上,除了說明不存在類,在 ECMA-262 中根本沒有出現「類」這個詞。ECMAScript 定義了「對象定義」,邏輯上等價於其餘程序設計語言中的類。指針

提示:本教程將使用術語「對象」。code

對象是由 new 運算符加上要實例化的對象的名字建立的。例如,下面的代碼建立 Object 對象的實例:對象

var o = new Object();

這種語法與 Java 語言的類似,不過當有不止一個參數時,ECMAScript 要求使用括號。若是沒有參數,如如下代碼所示,括號能夠省略:blog

var o = new Object;

注意:儘管括號不是必需的,可是爲了不混亂,最好使用括號。排序

提示:咱們會在對象基礎這一章中更深刻地探討對象及其行爲。

這一節的重點是具備等價的原始類型的引用類型。

Object 對象

Object 對象自身用處不大,不過在瞭解其餘類以前,仍是應該瞭解它。由於 ECMAScript 中的 Object 對象與 Java 中的 java.lang.Object 類似,ECMAScript 中的全部對象都由這個對象繼承而來,Object 對象中的全部屬性和方法都會出如今其餘對象中,因此理解了 Object 對象,就能夠更好地理解其餘對象。

Object 對象具備下列屬性:

constructor
對建立對象的函數的引用(指針)。對於 Object 對象,該指針指向原始的 Object() 函數。
Prototype
對該對象的對象原型的引用。對於全部的對象,它默認返回 Object 對象的一個實例。

Object 對象還具備幾個方法:

hasOwnProperty(property)
判斷對象是否有某個特定的屬性。必須用字符串指定該屬性。(例如,o.hasOwnProperty("name"))
IsPrototypeOf(object)
判斷該對象是否爲另外一個對象的原型。
PropertyIsEnumerable
判斷給定的屬性是否能夠用 for...in 語句進行枚舉。
ToString()
返回對象的原始字符串表示。對於 Object 對象,ECMA-262 沒有定義這個值,因此不一樣的 ECMAScript 實現具備不一樣的值。
ValueOf()
返回最適合該對象的原始值。對於許多對象,該方法返回的值都與 ToString() 的返回值相同。

註釋:上面列出的每種屬性和方法都會被其餘對象覆蓋。

Boolean 對象

Boolean 對象是 Boolean 原始類型的引用類型。

要建立 Boolean 對象,只須要傳遞 Boolean 值做爲參數:

var oBooleanObject = new Boolean(true);

Boolean 對象將覆蓋 Object 對象的 ValueOf() 方法,返回原始值,即 true 和 false。ToString() 方法也會被覆蓋,返回字符串 "true" 或 "false"。

遺憾的是,在 ECMAScript 中不多使用 Boolean 對象,即便使用,也不易理解。

問題一般出如今 Boolean 表達式中使用 Boolean 對象時。例如:

var oFalseObject = new Boolean(false);
var bResult = oFalseObject && true;	//輸出 true

在這段代碼中,用 false 值建立 Boolean 對象。而後用這個值與原始值 true 進行 AND 操做。在 Boolean 運算中,false 和 true 進行 AND 操做的結果是 false。不過,在這行代碼中,計算的是 oFalseObject,而不是它的值 false。

正如前面討論過的,在 Boolean 表達式中,全部對象都會被自動轉換爲 true,因此 oFalseObject 的值是 true。而後 true 再與 true 進行 AND 操做,結果爲 true。

注意:雖然你應該瞭解 Boolean 對象的可用性,不過最好仍是使用 Boolean 原始值,避免發生這一節提到的問題。

參閱

如需更多有關 Boolean 對象的信息,請訪問 JavaScript Boolean 對象參考手冊

Number 對象

正如你可能想到的,Number 對象是 Number 原始類型的引用類型。要建立 Number 對象,採用下列代碼:

var oNumberObject = new Number(68);

您應該已認出本章前面小節中討論特殊值(如 Number.MAX_VALUE)時提到的 Number 對象。全部特殊值都是 Number 對象的靜態屬性。

要獲得數字對象的 Number 原始值,只須要使用 valueOf() 方法:

var iNumber = oNumberObject.valueOf();

固然,Number 類也有 toString() 方法,在討論類型轉換的小節中已經詳細討論過該方法。

除了從 Object 對象繼承的標準方法外,Number 對象還有幾個處理數值的專用方法。

toFixed() 方法

toFixed() 方法返回的是具備指定位數小數的數字的字符串表示。例如:

var oNumberObject = new Number(68);
alert(oNumberObject.toFixed(2));  //輸出 "68.00"

在這裏,toFixed() 方法的參數是 2,說明應該顯示兩位小數。該方法返回 "68.00",空的字符串位由 0 來補充。對於處理貨幣的應用程序,該方法很是有用。toFixed() 方法能表示具備 0 到 20 位小數的數字,超過這個範圍的值會引起錯誤。

toExponential() 方法

與格式化數字相關的另外一個方法是 toExponential(),它返回的是用科學計數法表示的數字的字符串形式。

與 toFixed() 方法類似,toExponential() 方法也有一個參數,指定要輸出的小數的位數。例如:

var oNumberObject = new Number(68);
alert(oNumberObject.toExponential(1));  //輸出 "6.8e+1"

這段代碼的結果是 "6.8e+1",前面解釋過,它表示 6.8x101。問題是,若是不知道要用哪一種形式(預約形式或指數形式)表示數字怎麼辦?能夠用 toPrecision() 方法。

toPrecision() 方法

toPrecision() 方法根據最有意義的形式來返回數字的預約形式或指數形式。它有一個參數,即用於表示數的數字總數(不包括指數)。例如,

var oNumberObject = new Number(68);
alert(oNumberObject.toPrecision(1));  //輸出 "7e+1"

這段代碼的任務是用一位數字表示數字 68,結果爲 "7e+1",以另外的形式表示即 70。的確,toPrecision() 方法會對數進行舍入。不過,若是用 2 位數字表示 68,就容易多了:

var oNumberObject = new Number(68);
alert(oNumberObject.toPrecision(2));  //輸出 "68"

固然,輸出的是 "68",由於這正是該數的準確表示。不過,若是指定的位數多於須要的位數又如何呢?

var oNumberObject = new Number(68);
alert(oNumberObject.toPrecision(3));  //輸出 "68.0"

在這種狀況下,toPrecision(3) 等價於 toFixed(1),輸出的是 "68.0"。

toFixed()、toExponential() 和 toPrecision() 方法都會進行舍入操做,以便用正確的小數位數正確地表示一個數。

提示:與 Boolean 對象類似,Number 對象也很重要,不過應該少用這種對象,以免潛在的問題。只要可能,都使用數字的原始表示法。

參閱

如需更多有關 Number 對象的信息,請訪問 JavaScript Number 對象參考手冊

String 對象

String 對象是 String 原始類型的對象表示法,它是如下方式建立的:

var oStringObject = new String("hello world");

String 對象的 valueOf() 方法和 toString() 方法都會返回 String 類型的原始值:

alert(oStringObject.valueOf() == oStringObject.toString());	//輸出 "true"

若是運行這段代碼,輸出是 "true",說明這些值真的相等。

註釋:String 對象是 ECMAScript 中比較複雜的引用類型之一。一樣,本節的重點只是 String 類的基本功能。更多的高級功能請閱讀本教程相關的章節,或參閱 JavaScript String 對象參考手冊

length 屬性

String 對象具備屬性 length,它是字符串中的字符個數:

var oStringObject = new String("hello world");
alert(oStringObject.length);	//輸出 "11"

這個例子輸出的是 "11",即 "hello world" 中的字符個數。注意,即便字符串包含雙字節的字符(與 ASCII 字符相對,ASCII 字符只佔用一個字節),每一個字符也只算一個字符。

charAt() 和 charCodeAt() 方法

String 對象還擁有大量的方法。

首先,兩個方法 charAt() 和 charCodeAt() 訪問的是字符串中的單個字符。這兩個方法都有一個參數,即要操做的字符的位置。

charAt() 方法返回的是包含指定位置處的字符的字符串:

var oStringObject = new String("hello world");
alert(oStringObject.charAt(1));	//輸出 "e"

在字符串 "hello world" 中,位置 1 處的字符是 "e"。在「ECMAScript 原始類型」這一節中咱們講過,第一個字符的位置是 0,第二個字符的位置是 1,依此類推。所以,調用 charAt(1) 返回的是 "e"。

若是想獲得的不是字符,而是字符代碼,那麼能夠調用 charCodeAt() 方法:

var oStringObject = new String("hello world");
alert(oStringObject.charCodeAt(1));	//輸出 "101"

這個例子輸出 "101",即小寫字母 "e" 的字符代碼。

concat() 方法

接下來是 concat() 方法,用於把一個或多個字符串鏈接到 String 對象的原始值上。該方法返回的是 String 原始值,保持原始的 String 對象不變:

var oStringObject = new String("hello ");
var sResult = oStringObject.concat("world");
alert(sResult);		//輸出 "hello world"
alert(oStringObject);	//輸出 "hello "

在上面這段代碼中,調用 concat() 方法返回的是 "hello world",而 String 對象存放的仍然是 "hello "。出於這種緣由,較常見的是用加號(+)鏈接字符串,由於這種形式從邏輯上代表了真正的行爲:

var oStringObject = new String("hello ");
var sResult = oStringObject + "world";
alert(sResult);		//輸出 "hello world"
alert(oStringObject);	//輸出 "hello "

indexOf() 和 lastIndexOf() 方法

迄今爲止,已討論過鏈接字符串的方法,訪問字符串中的單個字符的方法。不過若是沒法肯定在某個字符串中是否確實存在一個字符,應該調用什麼方法呢?這時,可調用 indexOf() 和 lastIndexOf() 方法。

indexOf() 和 lastIndexOf() 方法返回的都是指定的子串在另外一個字符串中的位置,若是沒有找不到子串,則返回 -1。

這兩個方法的不一樣之處在於,indexOf() 方法是從字符串的開頭(位置 0)開始檢索字符串,而 lastIndexOf() 方法則是從字符串的結尾開始檢索子串。例如:

var oStringObject = new String("hello world!");
alert(oStringObject.indexOf("o"));		輸出 "4"
alert(oStringObject.lastIndexOf("o"));	輸出 "7"

在這裏,第一個 "o" 字符串出如今位置 4,即 "hello" 中的 "o";最後一個 "o" 出如今位置 7,即 "world" 中的 "o"。若是該字符串中只有一個 "o" 字符串,那麼 indexOf() 和 lastIndexOf() 方法返回的位置相同。

localeCompare() 方法

下一個方法是 localeCompare(),對字符串進行排序。該方法有一個參數 - 要進行比較的字符串,返回的是下列三個值之一:

  • 若是 String 對象按照字母順序排在參數中的字符串以前,返回負數。
  • 若是 String 對象等於參數中的字符串,返回 0
  • 若是 String 對象按照字母順序排在參數中的字符串以後,返回正數。

註釋:若是返回負數,那麼最多見的是 -1,不過真正返回的是由實現決定的。若是返回正數,那麼一樣的,最多見的是 1,不過真正返回的是由實現決定的。

示例以下:

var oStringObject = new String("yellow");
alert(oStringObject.localeCompare("brick"));		//輸出 "1"
alert(oStringObject.localeCompare("yellow"));		//輸出 "0"
alert(oStringObject.localeCompare("zoo"));		//輸出 "-1"

在這段代碼中,字符串 "yellow" 與 3 個值進行了對比,即 "brick"、"yellow" 和 "zoo"。因爲按照字母順序排列,"yellow" 位於 "brick" 以後,因此 localeCompare() 返回 1;"yellow" 等於 "yellow",因此 localeCompare() 返回 0;"zoo" 位於 "yellow" 以後,localeCompare() 返回 -1。再強調一次,因爲返回的值是由實現決定的,因此最好如下面的方式調用 localeCompare() 方法:

var oStringObject1 = new String("yellow");
var oStringObject2 = new String("brick");

var iResult = oStringObject1.localeCompare(oStringObject2);

if(iResult < 0) {
  alert(oStringObject1 + " comes before " + oStringObject2);
} else if (iResult > 0) {
  alert(oStringObject1 + " comes after " + oStringObject2);
} else {
  alert("The two strings are equal");
}

採用這種結構,能夠確保這段代碼在全部實現中都能正確運行。

localeCompare() 方法的獨特之處在於,實現所處的區域(locale,兼指國家/地區和語言)確切說明了這種方法運行的方式。在美國,英語是 ECMAScript 實現的標準語言,localeCompare() 是區分大小寫的,大寫字母在字母順序上排在小寫字母以後。不過,在其餘區域,狀況可能並不是如此。

slice() 和 substring()

ECMAScript 提供了兩種方法從子串建立字符串值,即 slice() 和 substring()。這兩種方法返回的都是要處理的字符串的子串,都接受一個或兩個參數。第一個參數是要獲取的子串的起始位置,第二個參數(若是使用的話)是要獲取子串終止前的位置(也就是說,獲取終止位置處的字符不包括在返回的值內)。若是省略第二個參數,終止位就默認爲字符串的長度。

與 concat() 方法同樣,slice() 和 substring() 方法都不改變 String 對象自身的值。它們只返回原始的 String 值,保持 String 對象不變。

var oStringObject = new String("hello world");
alert(oStringObject.slice("3"));		//輸出 "lo world"
alert(oStringObject.substring("3"));		//輸出 "lo world"
alert(oStringObject.slice("3", "7"));		//輸出 "lo w"
alert(oStringObject.substring("3", "7"));	//輸出 "lo w"

在這個例子中,slice() 和 substring() 的用法相同,返回值也同樣。當只有參數 3 時,兩個方法返回的都是 "lo world",由於 "hello" 中的第二個 "l" 位於位置 3 上。當有兩個參數 "3" 和 "7" 時,兩個方法返回的值都是 "lo w"("world" 中的字母 "o" 位於位置 7 上,因此它不包括在結果中)。

爲何有兩個功能徹底相同的方法呢?事實上,這兩個方法並不徹底相同,不過只在參數爲負數時,它們處理參數的方式才稍有不一樣。

對於負數參數,slice() 方法會用字符串的長度加上參數,substring() 方法則將其做爲 0 處理(也就是說將忽略它)。例如:

var oStringObject = new String("hello world");
alert(oStringObject.slice("-3"));		//輸出 "rld"
alert(oStringObject.substring("-3"));	//輸出 "hello world"
alert(oStringObject.slice("3, -4"));		//輸出 "lo w"
alert(oStringObject.substring("3, -4"));	//輸出 "hel"

這樣便可看出 slice() 和 substring() 方法的主要不一樣。

當只有參數 -3 時,slice() 返回 "rld",substring() 則返回 "hello world"。這是由於對於字符串 "hello world",slice("-3") 將被轉換成 slice("8"),而 substring("-3") 將被轉換成 substring("0")。

一樣,使用參數 3 和 -4 時,差異也很明顯。slice() 將被轉換成 slice(3, 7),與前面的例子相同,返回 "lo w"。而 substring() 方法則將兩個參數解釋爲 substring(3, 0),實際上即 substring(0, 3),由於 substring() 總把較小的數字做爲起始位,較大的數字做爲終止位。所以,substring("3, -4") 返回的是 "hel"。這裏的最後一行代碼用來講明如何使用這些方法。

toLowerCase()、toLocaleLowerCase()、toUpperCase() 和 toLocaleUpperCase()

最後一套要討論的方法涉及大小寫轉換。有 4 種方法用於執行大小寫轉換,即

  • toLowerCase()
  • toLocaleLowerCase()
  • toUpperCase()
  • toLocaleUpperCase()

從名字上能夠看出它們的用途,前兩種方法用於把字符串轉換成全小寫的,後兩種方法用於把字符串轉換成全大寫的。

toLowerCase() 和 toUpperCase() 方法是原始的,是以 java.lang.String 中相同方法爲原型實現的。

toLocaleLowerCase() 和 toLocaleUpperCase() 方法是基於特定的區域實現的(與 localeCompare() 方法相同)。在許多區域中,區域特定的方法都與通用的方法徹底相同。不過,有幾種語言對 Unicode 大小寫轉換應用了特定的規則(例如土耳其語),所以必須使用區域特定的方法才能進行正確的轉換。

var oStringObject = new String("Hello World");
alert(oStringObject.toLocaleUpperCase());	//輸出 "HELLO WORLD"
alert(oStringObject.toUpperCase());		//輸出 "HELLO WORLD"
alert(oStringObject.toLocaleLowerCase());	//輸出 "hello world"
alert(oStringObject.toLowerCase());		//輸出 "hello world"

這段代碼中,toUpperCase() 和 toLocaleUpperCase() 輸出的都是 "HELLO WORLD",toLowerCase() 和 toLocaleLowerCase() 輸出的都是 "hello world"。通常來講,若是不知道在以哪一種編碼運行一種語言,則使用區域特定的方法比較安全。

提示:記住,String 對象的全部屬性和方法均可應用於 String 原始值上,由於它們是僞對象。

instanceof 運算符

在使用 typeof 運算符時採用引用類型存儲值會出現一個問題,不管引用的是什麼類型的對象,它都返回 "object"。ECMAScript 引入了另外一個 Java 運算符 instanceof 來解決這個問題。

instanceof 運算符與 typeof 運算符類似,用於識別正在處理的對象的類型。與 typeof 方法不一樣的是,instanceof 方法要求開發者明確地確認對象爲某特定類型。例如:

var oStringObject = new String("hello world");
alert(oStringObject instanceof String);	//輸出 "true"

這段代碼問的是「變量 oStringObject 是否爲 String 對象的實例?」oStringObject 的確是 String 對象的實例,所以結果是 "true"。儘管不像 typeof 方法那樣靈活,可是在 typeof 方法返回 "object" 的狀況下,instanceof 方法仍是頗有用的。

相關文章
相關標籤/搜索