1. 程式人生 > >《JavaScript高階程式設計》第5章 引用型別

《JavaScript高階程式設計》第5章 引用型別

5章引用型別

ECMAScript中,引用型別是一種資料結構,用於將資料和功能組織在一起。儘管ECMAScript從技術上講是一門面向物件的語言,但它不具備傳統的面嚮物件語言所支援的類和介面等基本結構。

ECMAScript提供了很多原生引用型別,以便開發人員用以實現常見的計算任務。

Object型別:

建立Object例項的方式有兩種。第一種是使用new操作符後跟Object建構函式,例如var person = new Object();第二種是使用物件字面量表示法。物件字面量是物件定義的一種簡寫形式,目的在於簡化建立包含大量屬性的物件的過程。var person = { name: aaa

’,age:26};

一般來說,訪問物件屬性時使用的都是點表示法。不過,在JavaScript也可以使用方括號表示法來訪問物件的屬性。在使用方括號語法時,應該將要訪問的屬性以字串的形式放在方括號中。這兩種方式沒有區別,但方括號語法的主要優點是可以通過變數來訪問屬性。

Array型別:

ECMAScript陣列的每一項可以儲存任何型別的資料。而且,ECMAScript陣列的大小是可以動態調整的,即可以隨著資料的增加自動增長以容納新增資料。

建立陣列的基本方式有兩種:

1)使用Array建構函式,如var colors = new Array();如果預先知道陣列要儲存的專案數量,也可以給建構函式傳遞該數量,而該數量會自動變成length

屬性的值。也可以向Array建構函式傳遞陣列中應該包含的項。另外,在使用Array建構函式時也可以省略new操作符。

2)使用陣列字面量表示法,陣列字面量由一對包含陣列項的方括號表示。如var colors = [‘red’,’blue’];

檢測陣列:

Instanceof操作符的問題在於,它假設只有一個全域性執行環境,但實際中可能存在兩個不同的Array建構函式。為了解決這個問題,ECMAScript5新增了Array.isArray()方法。這個方法的目的是最終確定某個值到底是不是陣列。使用方法如if(Array.isArray(value)){ }

轉換方法:

所有物件都具有toLocaleString

()、toString()和valueOf()方法。其中,呼叫陣列的toString()方法會返回由陣列中每個值的字串形式拼接而成的一個以逗號分隔的字串。

toLocaleString()方法經常也會返回與toString()和valueOf()方法相同的值,但也不總如此,當呼叫陣列的toLocaleString()方法時,會呼叫每一項的toLocaleString()方法。

join()方法只接收一個引數,即用作分隔符的字串,然後返回包含所有陣列項的字串。

如果陣列中的某一項的值是null或者undefined,那麼該值在join()、toLocaleString()、toString()和valueOf()方法返回的結果中以空字串表示。

棧方法:

push()方法可以接收任意數量的引數,把它們逐個新增到陣列末尾,並返回修改後的陣列長度。

pop()方法則從陣列末尾移除最後一項,減少陣列的length值,然後返回移除的項。

佇列方法:

shift()方法能夠移除陣列中的第一個項並返回該項,同時將陣列長度減1

ECMAScript還為陣列提供一個unshift()方法,它能在陣列前端新增任意個項並返回新陣列的長度。

重排序方法:

陣列中已經存在兩個可以直接用來重排序的方法:reverse()和sort()。

預設情況下,為了實現排序,sort()方法會呼叫每個陣列項的toString()轉型方法,然後比較得到的字串。即使陣列中的每一項都是數值,sort()方法比較的也是字串。不用說,這種排序方法在很多情況下都不是最佳方案,因此sort()方法可以接收一個比較函式作為引數,以便我們指定哪個值位於哪個值的前面。

比較函式接收兩個引數,如果第一個引數應該位於第二個之前則返回一個負數,位於之後則返回一個正數,相等返回0

操作方法:

concat()方法先建立當前陣列一個副本,然後將接收到的引數新增到這個副本的末尾,最後返回新構建的陣列。

slice()方法它能夠基於當前陣列中的一個或多個項建立一個新陣列,可以接受一個或兩個引數,即要返回項的起始和結束位置。如果只有一個引數,則返回從該引數位置到結束的所有項。如果有兩個引數,該方法返回起始和結束位置之間的項,但不包括結束位置的項。注意slice()方法不會影響原始陣列。

splice()方法:始終都返回一個數組,該陣列中包含從原始陣列中刪除的項(如果沒有刪除的項,則返回一個空陣列)。

1)刪除:可以刪除任意數量的項,第一個引數是起始位置,第二個引數是項數;

2)插入:可以向指定位置插入任意數量的項,只需提供三個引數,起始位置、0(要刪除的項數)、要插入的項;

3)替換:可以向指定位置插入任意數量的項,同時刪除任意數量的項,只需三個引數:起始位置、要刪除的項數、要插入的項;

位置方法:

ECMAScript 5為陣列例項添加了兩個位置方法:indexOf()和lastIndexOf()。這兩個方法都接收兩個引數,要查詢的項和起點位置的索引。沒有找到返回-1,使用全等進行比較。

迭代方法:

ECMAScript 5為陣列定義了5個迭代方法。每個方法都接收兩個引數:要在每一項上執行的函式和執行該函式的作用域物件。傳入這些方法中的函式會接收三個引數:陣列項的值、該項在陣列中的位置和陣列物件本身。

every():對陣列中的每一項執行給定函式,如果該函式對每一項都返回true,則返回true

filter():對陣列中的每一項執行給定函式,返回該函式會返回true的項組成的陣列。

forEach():對陣列中的每一項執行給定函式,這個方法沒有返回值。

map():對陣列中的每一項執行給定函式,返回每次函式呼叫的結果組成的陣列。

some():對陣列中的每一項執行給定函式,如果該函式對任一項返回true,則返回true

歸併方法:

ECMAScript 5還新增了兩個歸併陣列的方法:reduce()和reduceRight()。這兩個方法都會迭代陣列的所有項,然後構建一個最終返回的值。這兩個方法都接收兩個引數:一個在每一項上呼叫的函式和作為歸併基礎的初始值。這個函式接收4個引數:前一個值、當前值、項的索引、陣列物件。應用場景:求陣列和。

Date型別:

ECMAScript中的Date型別是在早期Java中的java.util.Date類基礎上構建的。

在呼叫Date建構函式不傳遞引數時即獲得當前日期和時間,傳遞引數則需要毫秒數。為了簡化計算毫秒數,ECMAScript提供了兩個方法:Date.parse()和Date.UTC()。如new Date(Date.parse(“2/5/2018”));

new Date(Date.UTC(2018,1,5,12,12,12));

Date.now();方法返回表示呼叫這個方法時的日期和時間的毫秒數。在不支援Date.now()方法的瀏覽器中使用+操作符+new Date();也可以達到同樣的目的。

繼承的方法:

與其他引用型別一樣,Date型別也重寫了toLocaleString()、toString()和valueOf()方法;Date型別的toLocaleString()方法會按照與瀏覽器設定的地區相適應的返回日期和時間;toString()方法則通常返回帶有時區資訊的日期和時間;valueOf()方法返回日期的毫秒數。

日期格式化方法:

toDateString—顯示星期幾、月、日、年;toTimeString—顯示時、分、秒、時區;toLocaleTimeStringtoLocaleTimeStringtoUTCString

日期/時間元件方法:

getFullYear():取得4位數的年份;

getMonth():返回日期中的月份,其中0表示一月;

getDate():返回日期月份中的天數(131);

getDay():返回日期中星期的星期幾(0表示星期日);

getHours():返回日期中的小時數(023);

getMinutes():返回日期中的分鐘數(059);

getSeconds():返回日期中的秒數(059);

getMilliseconds():返回日期中的毫秒數;

RegExp型別:

var expression = /pattern/flags;

Flags可以是:g—表示全域性模式,即模式將被應用於所有字串,而非在發現第一個匹配項時立即停止;i—表示不區分大小寫模式;m—表示多行模式;

1)匹配第一個“bat“或”cat”,不區分大小寫var pattern1 = /[bc]at/I;

2)匹配所有以“at”結尾的3個字元的組合,不區分大小寫var pattern2 = /.at/gi;

對元字元匹配要使用轉義字元。

上面這兩個例子是以字面量形式來定義的正則表示式。另一種建立正則表示式的方式是使用RegExp建構函式,它接收兩個引數:一個是要匹配的字串模式,另一個是可選的標誌字串。var pattern3 = new RegExp(“[bc]at”,”i”);與pattern1相同。

由於RexExp建構函式的模式引數是字串,所以在某些情況下要對字串進行雙重轉義。

字面量模式/\[bc\]at/==== 等價的字串”\\[bc\\]at

使用正則表示式字面量和使用RegExp建構函式建立的正則表示式不一樣,在ECMAScript 3中,正則表示式字面量始終會共享一個RegExp例項,而使用建構函式建立的每一個新RegExp例項都是一個新例項。

ECMAScript 5明確規定,使用正則表示式字面量必須像直接呼叫RegExp建構函式一樣,每次都建立新的RegExp例項。

RegExp例項方法:

1RegExp物件的主要方法是exec(),該方法是專門為捕獲組而設計的。exec()接受一個引數,即要應用的字串,返回包含第一個匹配項資訊的陣列;或者沒有匹配項的情況下返回null。在陣列中,第一個項是與整個模式匹配的字串,其他項是與模式中的捕獲組匹配的字串。

對於exec()方法而言,在不設定全域性標誌的情況下,多次呼叫exec()將始終返回第一個匹配項的資訊。而在設定全域性標誌的情況下,每次呼叫exec()則都會在字串中繼續查詢新匹配項。

2)正則表示式的第二個方法是test(),它接受一個字串引數。在模式與該引數匹配的情況下返回true;否則返回false

RegExp例項繼承的toLocaleXString()和toString()方法都會返回正則表示式的字面量,與建立正則表示式的方式無關。

Function型別

函式實際上都是物件,每個函式都是Function型別的例項。由於函式是物件,因此函式名實際上也是一個指向函式物件的指標,不會與某個函式繫結。

函式宣告和函式表示式定義函式。解析器會率先讀取函式宣告,並使其在執行任何程式碼之前可用。至於函式表示式,則必須等到解析器執行到它所在的程式碼行,才會真正被解釋執行。

ECMAScript中沒有函式過載的概念,因為函式名只是函式物件的指標,會進行覆蓋。

在函式內部,有兩個特殊的物件:argumentsthisthis引用的是函資料以執行的環境物件或者也可以說是this值(當在網頁的全域性作用域中呼叫函式時,this物件引用的就是window)。

ECMAScript 5也規範了另一個函式物件的屬性:caller。這個屬性中儲存著呼叫當前函式的函式的引用。

每個函式都包含兩個屬性:lengthprototype。其中,length屬性表示函式希望接收的命名引數的個數。prototype是儲存它們所有例項方法的真正所在。在ECMAScript 5中,prototype屬性是不可列舉的,因此用for-in無法實現。

每個函式都包含兩個非繼承而來的方法:apply()和call()。這兩個方法的用途都是在特定的作用域中呼叫函式,實際上等於設定函式體內this物件的值。首先apply()方法接收兩個引數:一個是在其中執行函式的作用域,另一個是引數陣列。其中第二個引數可以是Array例項,也可以是arguments物件。call()方法與apply()方法的作用相同,區別僅在於引數的變化,call傳遞給函式的引數必須逐個列出來。使用call()或apply()來擴充作用域的最大好處,就是物件不需要與方法有任何耦合關係。

ECMAScript 5還定義了一個方法:bind()。這個方法給函式建立一個例項,其this值會被繫結到傳給bind()函式的值。

基本包裝型別

實際上,每當讀取一個基本型別值的時候,後臺就會建立一個對應的基本包裝型別的物件。

引用型別與基本包裝型別的主要區別就是物件的生存期,使用new操作符建立的引用型別例項,在執行流離開當前作用域之前都一直儲存在記憶體中,而自動建立的基本包裝型別的物件,則只存在於一行程式碼的執行瞬間,然後立即被銷燬。

Boolean型別:不建議使用,在使用typeof測試基本型別時返回boolean,測試引用型別時返回objectinstanceof測試基本型別時返回false,測試引用型別時返回true

Number型別:toFixed()方法傳入數值幾就表示顯示幾位小數。

String型別:

concat():連線字串

slice()、substr()、substring()方法都接受一個或兩個引數。第一個引數表示子字串起始位置,第二個引數為結束位置,對substr()來說第二個引數是字元個數。

indexOf()、lastIndexOf()這兩個方法都是從一個字串中搜索給定字串,然後返回子字串的位置,沒有找到則返回-1

trim():刪除字串前後空格。

字串的模式匹配方法:match()、search()、replace()方法。

localeCompare():這個方法比較兩個字串。

單體內建物件

ECMAScript實現提供的、不依賴於宿主環境的物件,這些物件在ECMAScript程式執行之前就已經存在了。例如ObjectArrayStringGlobalMath

1Global物件:“兜底兒物件”,換句話說,不屬於任何其他物件的屬性和方法,最終都是它的屬性和方法。

URI編碼方法:encodeURI()和encodeURIComponent()可以對URI進行編碼,以便傳送給瀏覽器。encodeURI不會對本身屬於URI的特殊字元進行編碼,例如冒號、正斜槓、問好、井字號;而encodeURIComponent()則會對它發現的任何非標準字元進行編碼。

Global物件還包含一些屬性,例如,特殊的值undefinedNaN以及Infinity都是Global物件的屬性,此外,所有原生引用型別的建構函式,像ObjectFunction,也都是Global物件的屬性。

ECMAScript雖然沒有指出如何直接訪問Global物件,但Web瀏覽器都是將這個全域性物件作為window物件的一部分加以實現的。

Math物件

Math.ceil()執行向上舍入,即它總是將數值向上舍入為最接近的整數。

Math.floor()執行向下舍入,即它總是將數值向下舍入為最接近的整數。

Math.round()執行標準舍入,即它總是將數值四捨五入為最接近的整數。

Math.random()方法返回大於等於0小於1的一個隨機數。

從某個整數範圍內隨機選擇一個值:

= Math.floor(Math.random()*可能值的總數 + 第一個可能的值)