[JavaScript] 引用類型

1. 原生引用類型


1.1 引用類型和類

引用類型是一種數據結構,用於將數據和功能組織在一起,也常稱做類。ECMAScript從技術上說是一門面向對象的語言,但它不具備傳統的面嚮對象語言所支持的類和接口等基本結構。


1.2 Object類型

大多數引用類型的值都是Object類型的實例,創建object實例的方式有兩種,第一種是使用new操作符,例如:

var myobj = new Object();

另一種方式是使用對象字面量表示法,例如:

var myobj  = {
  name : "obj",
  weight : 20
};

如果留空其花括號,則可以定義只包含默認屬性和方法的對象,例如:

var myobj = {};

一般來說,訪問對象屬性時使用的都是點表示法,也可以使用方括號一膚淺法來訪問對象的屬性,例如:

var myobj = {
  name = "obj"
}
alert(myobj["name"]);


1.3 Array類型

ECMAScript數組的每一項可以保存任何類型的數據,而且,數組的大小是可以動態調整的,即隨着數據的添加自動增長以容納新增數據。創建數組有兩種形式,第一種是使用Array構造函數,例如:

var myarray = new Array();

也可以給Array構造函數傳遞數組要保存的項目數量,例如:

var myarray = new Array(20);

也可以向Array構造函數傳遞數組中應該包含的項,例如:

var myarray = new Array("a", "b", "c");

使用Array構造函數時也可以省略new操作符,第二種創建數組的方式是使用數組字面量表示法,例如:

var myarray = ["a", "b", "c"];

在讀取數組的值時,要使用方括號並提供相應值的基於0的數字索引,例如:

alert(myarray[0]);

數組的項數保存在其length屬性中,例如:

alert(myarray.length);

這個屬性不是隻讀的,可以通過設置這個屬性,從數組的末尾移除項或向數組中添加新項。


1.4 Array方法

所有對象都具有toLocaleString()、toString()和valueOf()方法,其中,調用數組的toString()和valueOf()方法會返回相同的值,即由數組中每個值的字符串形式拼接而成的一個以逗號分隔的字符串。實際上,它會調用數組每一項的toString()方法,而toLocaleString()方法則是調用數組每一項的toLocaleString()方法

ECMAScript數組也提供了一種讓數組行爲類似於其他數據結構的方法:push()和pop()。push()方法可以接收任意數量的參數,把它們逐個添加到數組末尾,並返回修改後數組的長度,而pop()方法則從數組末尾移除最後一項,然後返回移除的項,例如:

myarray.push("d");
myarray.pop();

此外,ECMAScript數組還提供了類似隊列行爲的方法:shift()和unshift()。shift()能夠移除數組中的第一個項並返回該項,而unshift()相反,它能在數組前端添加任意個項並返回數組的長度,例如:

myarray.shift();
myarray.unshift("A", "B");

數組中已經存在兩個可以直接用來重排序的方法:reverse()和sort()。reverse()方法會反轉數組項的順序,而sort()方法按升序排列數組項,例如:

myarray.reverse();
myarray.sort();

最後,ECMAScript爲操作已經包含在數組中的項提供了很多方法。其中,concat()方法也可基於當前數組中的所有項創建一個新數組,在沒有傳遞參數的情況下,它只是複製當前數組並返回副本,如果傳遞給concat()方法的是一或多個數組,則該方法會將這些數組中的每一項都添加到結果數組中,如果傳遞的值不是數組,這些值就會被簡單地添加到結果數組的末尾。

slice()方法能夠基於當前數組中的一或多個項創建一個新數組,它可以接受一或兩個參數,即要返回項的起始和結束位置,只有一個參數的情況下,slice()方法返回從該參數指定位置開始到當前數組末尾的所有項。

splice()方法的主要用途是向數組的中部插入項,它有很多種用法,如果提供兩個參數(要刪除的第一項的位置和要刪除的項數),則會刪除數組中的項,如果提供三個參數(起始位置,要刪除項數,要插入的項),則可以實現在數組中插入元素。


1.5 Date類型

Date類型使用自UTC1970年1月1日午夜開始經過的毫秒數來保存日期,在使用這種存儲格式的條件下,Date類型保存的日期能夠精確到1970年1月1日之前或之後的285616年。

創建一個日期對象,使用new操作符和Date構造函數即可,例如:

var now = new Date();

在不傳遞參數的情況下,新創建的對象自動獲得當前日期和時間,如果想根據特定的日期和時間創建日期對象,必須傳入表示該日期的毫秒數。爲了簡化這一過程,ECMAScript提供了兩個方法:Date.parse()和Date.UTC()。

Date.parse()方法接收一個表示日期的字符串參數,嘗試根據這個字符串返回相應日期的毫秒數,如果傳入Date.parse()方法的字符串不能表示日期,那麼它會返回NaN,例如:

var mydate = new Date(Date.parse("May 01, 2000"));

Date.UTC()方法同樣也返回表示日期的毫秒數,但它與Date.parse()在構建值時使用不同的信息。Date.UTC()的參數分別是年份、基於0的月份(一月是0)、月中的哪一天(1到31)、小時數(0到23)、分鐘、秒以及毫秒數,只有前兩個參數是必須的,如果省略其他參數,則一律設爲0,例如:

var mydate = new Date(Date.UTC(2000, 1, 1, 8, 10, 10));


1.6 Date方法

Date類型也重寫了toLocaleString()、toString()和valueOf()方法,但這些方法返回的值與其他類型中的方法不同。toLocaleString()方法會按照與瀏覽器設置的地區相適應的格式返回日期和時間。而toString()方法則通常返回帶有時區信息的日期和時間。valueOf()方法根本不返回字符串,而是返回日期的毫秒錶示。

Date類型還有一些用於將日期格式化爲字符串的方法。

1) toDateString: 以特定於實現的格式顯示星期幾、月、日和年。

2) toTimeString: 以特定於實現的格式顯示時、分、秒和時區。

3) toLocaleDateString: 以特定於地區的格式顯示星期幾、月、日和年。

4) toLocaleTimeString: 以特定於地區的格式顯示時、分、秒。

5) toUTCString(): 以特定於實現的格式完整的UTC日期。

此外,還有一些Date類型的方法,都是直接取得和設置日期中特定部分的方法,UTC日期指的是在沒有時區偏差的情況下的日期值。

日期時間組件方法
方法
說明
getTime()返回表示日期的毫秒數。
setTime()以毫秒數設置日期。
getFullYear()取得4位數年份。
getUTCFullYear()取得UTC日期的4位數年份。
setFullYear()以4位數字設置年份。
setUTCFullYear()以4位數字設置UTC日期的年份。
getMonth()取得月份(0表示1月)。
getUTCMonth()取得UTC日期月份(0表示1月)。
setMonth()設置月份,超過11則增加年份。
setUTCMonth()設置UTC日期月份,超過11則增加年份。
getDate()取得天數(1到31)。
getUTCDate()取得UTC日期天數(1到31)。
setDate()設置天數,超過該月中應有的天數,則增加月份。
setUTCDate()設置UTC日期天數,超過該月中應有的天數,則增加月份。
getDay()取得星期中的星期幾。
getUTCDay()取得UTC日期星期中的星期幾。
getHours()取得小時數(0到23)。
getUTCHours()取得UTC日期小時數(0到23)。
setHours()設置小時數,超過23則增加天數。
setUTCHours()設置UTC日期小時數,超過23則增加天數。
getMinutes()取得分鐘數(0到59)。
getUTCMinutes()取得UTC日期分鐘數(0到59)。
setMinutes()設置分鐘數,超過59則增加小時數。
setUTCMinutes()設置UTC日期分鐘數,超過59則增加小時數。
getSeconds()取得秒數(0到59)。
getUTCSeconds()取得UTC日期秒數(0到59)。
setSeconds()設置秒數,超過59則增加分鐘數。
setUTCSeconds()設置UTC日期秒數,超過59則增加分鐘數。
getMilliseconds()取得毫秒數。
getUTCMilliseconds()取得UTC日期毫秒數。
setMilliseconds()設置毫秒數。
setUTCMilliseconds()設置UTC日期毫秒數。
getTimezoneOffset()返回本地時間與UTC時間相差的分鐘數。


1.7 RegExp類型

ECMAScript通過RegExp類型來支持正則表達式,語法如下:

var expression = /pattern/ flags;

其中模式(pattern)部分是正則表達式,每個正則表達式都可帶有一或多個標誌(flag)。正則表達式的匹配模式支持以下3個標誌:

1) g: 表示全局模式,即模式將被用於所有字符串,而非在發現第一個匹配項時停止。

2) i: 表示不區分大小寫模式。

3) m: 表示多行模式,即在到達一行文本末尾時還會繼續查找下一行。

RegExp的每個實例具有以下屬性:

1) global: 布爾值,表示是否設置了g標誌。

2) ignoreCase: 布爾值,表示是否設置了i標誌。

3) lastIndex: 整數,表示開始搜索下一個匹配項的字符位置,從0開始。

4) multiline: 布爾值,表示是否設置了m標誌。

5) source: 正則表達式的字符中表示。

ECMAScript中的正則表達式仍然缺少某些語言支持的高級正則表達式特性,如下:

1) 匹配字符串開始和結尾的\A和\Z錨。

2) 向後查找。

3) 並集和交集類。

4) 原子組。

5) Unicode支持(單個字符除外)。

6) 命名的捕獲組。

7) s和x匹配模式。

8) 條件匹配。

9) 正則表達式註釋。


1.8 RegExp方法

RegExp對象的主要方法是exec(),它接受一個參數,即要應用模式的應符串,然後返回包含第一個匹配項信息的數組,沒有匹配項的情況下返回null。返回的數組是Array()的實例,但包含兩個額外屬性index和input,index表示匹配項在字符串中的位置,input表示應用正則表達式的字符串,例如:

var input = "this is a test";
var pattern = /test/gi;
var matches = pattern.exec(text);
alert(matches.index);
alert(matches.input);
alert(matches[0]);

對於exec()方法,即使設置了模式g,每次也只返回一個匹配項,但每次調用都會在字符串中繼續查找新匹配項。

另一個方法是test(),它接受一個字符串參數,在模式與參數匹配的情況下返回true,否則返回false,例如:

var input = "this is a test";
var pattern = /test/gi;
alert(pattern.test());

RegExp繼承的toLocaleString()和toString()方法都會返回正則表達式的字面量。


1.9 RegExp屬性

RegExp構造函數包含一些屬性,這些屬性可以通過兩種方式訪問它們,一個長屬性名,一個短屬性名(Opera不支持短屬性名)。

RegExp構造函數屬性
長屬性名
短屬性名說明
Input$_最近一次要匹配的字符串(Opera不支持)。
lastMath$&最近一次的匹配項(Opera不支持)。
lastParen$+最近一次匹配的捕獲組(Opera不支持)。
lastContext$`input字符串中lastMatch之前的文本。
multiline$*是否所有表達式都使用多行模式(IE和Opera不支持)。
rightContext$'input字符串中lastMatch之後的文本。


1.10 Function類型

函數實際上是對象,每個函數都是Function對象的實例,而且都與其他引用類型一樣具有屬性和方法。函數名實際上也是一個指向函數的指針,不會與某個函數綁定。函數通常使用函數聲明語法定義,例如:

function myfunc(myvar) {
  return myvar;
}

也可以使用如下方式 :

var myfunc = function(myvar) {return myvar;};

第二種方式是使用Function構造函數,它可以接收任意數量的參數,但最後一個參數始終都被看成是函數體,例如:

var myfunc = new Function("myvar", "return myvar;");

但是不推薦使用這種方式,因爲這種語法會導致解析兩次代碼,從而影響性能,但這種語法有助於理解函數是對象的概念。

如果聲明兩個同名函數,結果就是後面的函數覆蓋了前面的函數,因爲函數名相當於指針。

解析器在執行環境中加載數據時,會率先讀取函數聲明,並使其在執行任何代碼前可用,但函數表達式則必須等到解析器執行到它所在的代碼行,纔會被真正解析執行,例如:

alert(myfunc1(1)); //正確
function myfunc1(myvar) {
  return myvar;
}
alert(myfunc2(1)); //錯誤
var myfunc2 = function(myvar) {
  return myvar;
}

因爲ECMAScript中函數名本身就是變量,所以函數也可以作爲值來使用,比如可以將一個函數作爲另一個函數的結果返回,例如:

function myfunc() {
  return function() {
    return 1;
  }
}


1.11 Function方法

每個函數都包含兩個非繼承而來的方法:apply()和call()。這兩個方法的用途都是在特定的作用域中調用函數。

apply()方法接受兩個參數,一個是在其中運行函數的作用域,另一個是參數數組,第二個參數可以是Array的實例,也可以是arguments對象,例如:

function myfunc1() {
}
function myfunc2() {
  return myfunc1.apply(this, arguments);
}

call()方法與apply()方法的作用相同,只是在於接收參數的方式不同,對於call()方法而言,第一個參數是作用域,其餘參數都是直接傳遞給函數的,例如:

function myfunc1() {
}
function myfunc2(myvar) {
  return myfunc1.call(this, myvar);
}


1.12 Function屬性

ECMAScript中的函數是對象,所有也有屬性和方法,每個函數都包含兩個屬性:length和prototype。其中length屬性表示函數希望接收的命名參數的個數。

對於ECMAScript中的引用類型而言,prototype是保存它們所有實例方法的真正所在,例如toString()和valueOf()等方法實際都保存在prototype名下,只不是通過各自對象的實例訪問,在創建自定義引用類型及實現繼承時,prototype屬性極爲重要。

在函數內部,有兩個特殊的對象:arguments和this.arguments包含傳入函數中的所有參數,這個對象還有一個callee屬性,該屬性是一個指針,指向擁有這個agruments對象的函數。this與Java和C#中的this大致類似,引用的是函數據以執行操作的對象,或者說this是函數在執行時所處的作用域。


2. 基本包裝類型


2.1 Boolean類型

Boolean類型是與布爾值對應的引用類型,要創建Boolean對象,可以調用Boolean構造函數,並傳入true或false值,例如:

var booleanObject = new Boolean(false);

Boolean類型重寫了valueOf()方法,返回基本類型值true或false。重寫了toString()方法,返回字符串"true"或"false"。但是Boolean類型容易引用誤解,例如:

var falseObject = new Boolean(false);
alert(falseObject && true); //true

示例中的代碼是對falseObject而不是對它的值求值,布爾表達式中的所有對象都會被轉換成true,因此示例的結果是true。


2.2 Number類型

Number是與數字值對應的引用類型,要創建Number對象,可以調用Number構造函數並傳入相應的數值,例如:

var numberObject = new Number(1);

Number類型重寫了valueOf()方法,返回對象表示的基本類型數值。重寫了toLocaleString()和toString(),返回字符串形式的數值。

除了繼承的方法外,Number類型還提供了一些用於將數值格式化的方法。toFixed()方法按照指定的小數返回數值的字符串表示,例如:

var num = 1;
alert(num.toFixed(2));

如果數值本身包含的小數位比指定的還多,那麼接近指定的最大小數位的值就會舍入,例如:

var num = 1.005;
alert(num.toFixed(2));

toExponential()方法返回以指數表示法表示的數值的字符串形式,它接收一個參數,指定輸出結果中的小數位數,例如:

var num = 1;
alert(num.toExponential(1));


2.3 String類型

String類型是字符串的對象包裝類型,可以使用String構造函數來創建,例如:

var stringObject = new String("Hello World!");

String對象繼承的valueOf()、toLocaleString和toString()方法都返回對象所表示的基本字符串值。

String對象都有length屬性,表示字符串中包含多個字符,例如:

var mystr = "Hello World!";
alert(mystr.length);


2.4 String方法

兩個用於訪問字符串中特定字符的方法是:charAt()和charCodeAt()。這兩個方法都接收一個參數,即基於0的字符位置。charAt()方法以單字符字符串的形式返回給定位置的那個字符,而charCodeAt()方法返回的不是字符而是字符編碼,例如:

var mystr = "Hello World!";
alert(mystr.charAt(1));
alert(mystr.charCodeAt(1));

String構造函數本身有一個靜態方法:fromCharCode(),這個方法是接收一個或多個字符編碼,然後將它們轉換成一個字符串,與charCodeAt()執行的是相反的操作,例如:

alert(String.fromCharCode(104, 101, 108, 108, 111));

還有幾個與操作字符串有關的方法,第一個是concat(),用於將一或多個字符串拼接起來,返回拼接得到的新字符串,例如:

var mystr = "Hello";
alert(mystr.concat(" World!"));

雖然concat()是專門用來拼接字符串的方法,但是使用更多的是加號操作符,在大多數情況下,加號操作符比concat()方法簡便。

另外三個是基於子字符串創建新字符串的方法:slice()、substr()和substring()。這三個方法都返回被操作字符串的一個子字符串,都接受一或兩個參數。第一個參數指定子字符串的開始位置,第二個參數表示子字符串到哪裏結束。slice()和substring()的第二個參數指定的是子字符串最後一個字符後面的位置,而substr()的第二個參數指定的則是返回的字符個數。如果沒有指定第二個參數,則將字符串的長度作爲結束位置,例如:

var mystr = "Hello World!";
alert(mystr.slice(3, 6));
alert(mystr.substr(3, 6));
alert(mystr.substring(3, 6));

有兩個可以從字符串中查找子符串的方法:indexOf()和lastIndexOf()。這兩個方法都是從一個字符串搜索給定的子字符串,返回子字符串的位置,如果沒有找到,則返回-1。但indexOf()方法從字符串開頭向後搜索,而lastIndexOf()方法是從字符串的末尾向前搜索,例如:

var mystr = "Hello World!";
alert(mystr.indexOf("o"));
alert(mystr.lastIndexOf("o"));

ECMAScript中涉及字符串大小寫轉換的方法有4個:toLowerCase()、toLocaleLowerCase()、toUpperCase()和toLocaleUpperCase()。toLowerCase()和toUpperCase()方法分別指字符串轉換爲小寫和大寫,而toLocaleLowerCase()和toLocaleUpperCase()方法則是針對特定地區的實現,例如:

var mystr = "Hello World";
alert(mystr.toLowerCase());
alert(mystr.toUpperCase());
alert(mystr.toLocaleLowerCase());
alert(mystr.toLocaleUpperCase());

與操作字符串有關的最後一個方法是localeCompare(),這個方法比較兩個字符串,並返回下列值中的一個:

1) 如果字符串在字母表中的順序在參數之前,則返回一個負數。

2) 如果字符串等於參數,則返回0.

3) 如果字符串在字母表中的順序在參數之後,則返回一個正數。


2.5 String的模式匹配

String類型定義了幾個用於在字符串中匹配模式的方法。第一個方法是match(),在字符串上調用這個方法,本質上與調用RegExp的exec()方法相同,例如:

var input = "this is a test";
var pattern = /is/;
var matches = input.match(pattern);

另一個用於查找模式的方法是search(),這個方法的唯一參數也是一個正則表達式。search()方法返回字符串中第一個匹配項的索引,如果沒有找到匹配項,則返回-1,例如:

var input = "this is a test";
var pos = input.search(/is/);
alert(pos);

ECMAScript還提供了用於替換子字符串的replace()方法,這個方法接收兩個參數:正則表達式和一個字符串或函數。如果第一個參數是字符串,那麼只會替換第一個子字符串,要替換所有子字符串,要提供正則表達式並指定全局標誌,例如:

var input = "this is a test";
alert(input.replace(/s/g, "a"));

如果第二個參數是字符串,那麼還可以使用特殊字符序列,將正則表達式操作得到的值插入到結果字符串中,例如:

var input = "this is a test";
alert(input.replace(/(s)/g), "result: ($1)");
特殊字符序列
字符序列
替換文本
$$$
$&匹配整個模式的子字符串。
$'匹配的子字符串之前的子字符串。
$`匹配的子字符串之後的子字符串。
$n匹配第n個捕獲組的子字符串。
$nn匹配第nn個捕獲組的子字符串。

最後一個與模式匹配有關的方法是split(),這個方法可以基於指定的分隔符將一個字符串分割成多個子字符串,並將結果放在一個數組中。分隔符可以是字符串,也可以是正則表達式,split()方法接受可選的第二個參數,用於指定數組的大小,例如:

var mystr = "a, b, c, d";
var myarray = mystr.split(",");


3. 內置對象


3.1 Global對象

所有在全局作用域中定義的屬性和函數,都是Global對象的屬性,例如isNan()、isFinite()、parseInt()和parseFloat(),換句話說,不屬於任何其他對象的屬性和方法,最終都是Global對象的屬性和方法。

Global對象的encodeURI()和encodeURIComponent()方法可以對URI進行編碼,encodeURI()主要用於整個URI,而encodeURIComponent()主要用於對URI中的某一段進行編碼。主要區別在於,encodeURI()不會地本身屬於URI的特殊字符進行編碼,而encodeURIComponent()會地它發現的任何非標準字符進行編碼,例如:

var uri = "http://www.test.com/";
alert(encodeURI(uri));
alert(encodeURIComponent(uri));

與encodeURI()和encodeURIComponent()方法對應的兩個方法分別是decodeURI()和decodeURIComponent()。

另一個方法,也是ECMAScript中最強大的方法:eval()。eval()方法像是一個ECMAScript解析器,它接受一個參數,即要執行的ECMAScript字符串,例如:

eval("alert('Hello World!')");

通過eval()執行的代碼被認爲是包含該次調用的執行環境的一部分,被執行的代碼具有與該執行環境相同的作用域鏈。

Global對象還包含一些屬性,例如undefined、NaN和Infinity。此外,所有原生引用類型的構造函數,也是Global對象的屬性。

Global對象屬性
屬性
說明
undefined特殊值undefined
NaN特殊值NaN
Infinity特殊值Infinity
Object構造函數Object
Array構造函數Array
Function構造函數Function
Boolean構造函數Boolean
String構造函數String
Number構造函數Number
Date構造函數Date
RegExp構造函數RegExp
Error構造函數Error
EvalError構造函數EvalError
RangeError構造函數RangeError
ReferenceError構造函數ReferenceError
SyntaxError構造函數SyntaxError
TypeError構造函數TypeError
URIError構造函數URIError


3.2 window對象

ECMAScript沒有指出如何直接訪問Global對象,但WEB瀏覽器都是將它作爲window對象的一部分加以實現的,例如:

var mystr = "Hello World!";
alert(window.mystr);


3.3 Math對象

ECMAScript爲保存數學公式提供了一個Math對象。

Math對象的屬性大都是數學計算中可能會用到的一些特殊值。

Math對象屬性
屬性
說明
Math.E自然對數底數E的值
Math.LN1010的自然對數
Math.LN22的自然對數
Math.LOG2E以2爲底e的對數
Math.LOG10E以10爲底e的對數
Math.PIπ的值
Math.SQRT1_21/2的平方根
Math.SQRT22的平方根

Math對象還包含許多方法,用於完成簡單的數學計算。其中,min()和max()方法用於確定一組數值中的最小值和最大值,例如:

var max = Math.max(1, 2, 3, 4);
var min = Math.min(1, 2, 3, 4);

還有幾個用於舍入的方法:Math.ceil()、Math.floor()和Math.round()。Math.ceil()執行向上舍入,Math.floor()執行向下舍入,Math.round()執行標準舍入,例如:

alert(Math.ceil(25.5));
alert(Math.floor(25.5));
alert(Math.round(25.5));

Math.random()方法返回介於0和1之間一個隨機數,不包括0和1,例如:

var num = Math.random();

Math對象還包含其他一些計算方法 ,不一一列舉。

Math對象方法
方法
說明
Math.abs(num)返回num的絕對值。
Math.exp(num)返回Math.E的num次幕。
Math.log(num)返回num的自然對數。
Math.pow(num, power)返回num的power次冪。
Math.sqrt(num)返回num的平方根。
Math.acos(x)返回x的反餘弦值。
Math.asin(x)返回x的反正弦值。
Math.atan(x)返回x的反正切值。
Math.atan2(y, x)返回y/x的反正切值。
Math.cos(x)返回x的餘弦值。
Math.sin(x)返回x的正弦值。
Math.tan(x)返回x的正切值



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章