《Javascript 高階程式設計(第三版)》筆記0x6 引用型別(1)
目錄
引用型別的值(物件)是引用型別的一個例項。在 ECMAScript 中, 引用型別是一種資料結構,用於將資料和功能組織在一起。不能稱作類,它不具備傳統的面嚮物件語言所支援的類和介面等基本結構。引用型別有時候也被稱為物件定義,因為它們描述的是一類物件所具有的屬性和方法。
var person = new Object();
/*
* 這行程式碼建立了 Object 引用型別的一個新例項,然後把該例項儲存在了變數 person 中。使用
* 的建構函式是 Object,它只為新物件定義了預設的屬性和方法。
*/
Object型別
//new 操作符後跟 Object 建構函式
var person = new Object();
person.name = "Nicholas";
person.age = 29;
//物件字面量表示法
var person = {
name : "Nicholas",
age : 29
};
var person = {//屬性可用字串,數字會自動轉字串
"name" : "Nicholas",
"age" : 29,
5 : true
};
var person = {}; //與 new Object()相同
person.name = "Nicholas";
person.age = 29;
function displayInfo(args) {
var output = "";
if (typeof args.name == "string"){
output += "Name: " + args.name + "\n";
}
if (typeof args.age == "number") {
output += "Age: " + args.age + "\n";
}
alert(output);
}
displayInfo({
name: "Nicholas",
age: 29
});
displayInfo({
name: "Greg"
});
//使用方括號表示法來訪問物件的屬性
alert(person["name"]); //"Nicholas"
alert(person.name); //"Nicholas"
var propertyName = "name";//方括號語法的主要優點是可以通過變數來訪問屬性
alert(person[propertyName]); //"Nicholas"
//如果屬性名中包含會導致語法錯誤的字元,或者屬性名使用的是關鍵字或保留字,也可以使用方括號表示法。
person["first name"] = "Nicholas";
Array 型別
ECMAScript 陣列的每一項可以儲存任何型別的資料,大小是可以動態調整的,即可以隨著資料的新增自動增長以容納新增資料。
//使用 Array 建構函式建立陣列
var colors = new Array();
var colors = new Array(20);
var colors = new Array("red", "blue", "green");
var colors = Array(3); // 建立一個包含 3 項的陣列
var names = Array("Greg"); // 建立一個包含 1 項,即字串"Greg"的陣列
//陣列字面量表示法建立陣列
var colors = ["red", "blue", "green"]; // 建立一個包含 3 個字串的陣列
var names = []; // 建立一個空陣列
var values = [1,2,]; // 不要這樣!這樣會建立一個包含 2 或 3 項的陣列
var options = [,,,,,]; // 不要這樣!這樣會建立一個包含 5 或 6 項的陣列
//讀取和設定陣列
var colors = ["red", "blue", "green"]; // 定義一個字串陣列
alert(colors[0]); // 顯示第一項
colors[2] = "black"; // 修改第三項
colors[3] = "brown"; // 新增第四項
//陣列項數
var colors = ["red", "blue", "green"]; // 建立一個包含 3 個字串的陣列
var names = []; // 建立一個空陣列
alert(colors.length); //3
alert(names.length); //0
//利用設定陣列項數刪除末尾項
var colors = ["red", "blue", "green"]; // 建立一個包含 3 個字串的陣列
colors.length = 2;
alert(colors[2]); //undefined
var colors = ["red", "blue", "green"]; // 建立一個包含 3 個字串的陣列
colors.length = 4;
alert(colors[3]); //undefined
//利用 length 屬性也可以方便地在陣列末尾新增新項
var colors = ["red", "blue", "green"]; // 建立一個包含 3 個字串的陣列
colors[colors.length] = "black"; //(在位置 3)新增一種顏色
colors[colors.length] = "brown"; //(在位置 4)再新增一種顏色
陣列最多可以包含 4 294 967 295 個項。
檢測陣列
//確定某個物件是不是陣列,假定只有一個全域性執行環境
if (value instanceof Array){
//對陣列執行某些操作
}
//最終確定某個值到底是不是陣列,而不管它是在哪個全域性執行環境中建立的。
if (Array.isArray(value)){
//對陣列執行某些操作
}
轉換方法
toString(),valueOf()
var colors = ["red", "blue", "green"]; // 建立一個包含 3 個字串的陣列
alert(colors.toString()); // red,blue,green
alert(colors.valueOf()); // red,blue,green
alert(colors); // red,blue,green
toLocaleString()
//呼叫了陣列每一項的toLocaleString()方法
var person1 = {
toLocaleString : function () {
return "Nikolaos";
},
toString : function() {
return "Nicholas";
}
};
var person2 = {
toLocaleString : function () {
return "Grigorios";
},
toString : function() {
return "Greg";
}
};
var people = [person1, person2];
alert(people); //Nicholas,Greg
alert(people.toString()); //Nicholas,Greg
alert(people.toLocaleString()); //Nikolaos,Grigorios
join()
//用 join()方法重現了 toString()方法的輸出
var colors = ["red", "green", "blue"];
alert(colors.join(",")); //red,green,blue
alert(colors.join("||")); //red||green||blue
如果陣列中的某一項的值是 null 或者 undefined,那麼該值在 join()、toLocaleString()、 toString()和 valueOf()方法返回的結果中以空字串表示。
棧方法
棧是一種 LIFO(Last-In-First-Out,後進先出)的資料結構
push(),pop()
var colors = new Array(); // 建立一個數組
var count = colors.push("red", "green"); // 推入兩項
alert(count); //2
count = colors.push("black"); // 推入另一項
alert(count); //3
var item = colors.pop(); // 取得最後一項
alert(item); //"black"
alert(colors.length); //2
佇列方法
佇列資料結構的訪問規則是 FIFO(First-In-First-Out,先進先出)
push(),shift(),unshift()
var colors = new Array(); //建立一個數組
var count = colors.push("red", "green"); //推入兩項
alert(count); //2
count = colors.push("black"); //推入另一項
alert(count); //3
var item = colors.shift(); //取得第一項
alert(item); //"red"
alert(colors.length); //2
//unshift()與 shift()的用途相反:它能在陣列前端新增任意個項並返回新陣列的長度。
var colors = new Array(); //建立一個數組
var count = colors.unshift("red", "green"); //推入兩項
alert(count); //2
count = colors.unshift("black"); //推入另一項
alert(count); //3
var item = colors.pop(); //取得最後一項
alert(item); //"green"
alert(colors.length); //2
重排序方法
reverse()
//reverse()
var values = [1, 2, 3, 4, 5];
values.reverse();
alert(values); //5,4,3,2,1
sort()
//sort(),呼叫每個陣列項的 toString()轉型方法,然後比較得到的字串
//即使陣列中的每一項都是數值, sort()方法比較的也是字串
var values = [0, 1, 5, 10, 15];
values.sort();
alert(values); //0,1,10,15,5進行字串比較時, "10"則位於"5"的前面
//比較函式
function compare(value1, value2) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
var values = [0, 1, 5, 10, 15];
values.sort(compare);
alert(values); //0,1,5,10,15
操作方法
concat()
//concat()方法可以基於當前陣列中的所有項建立一個新陣列
var colors = ["red", "green", "blue"];
var colors2 = colors.concat("yellow", ["black", "brown"]);
alert(colors); //red,green,blue
alert(colors2); //red,green,blue,yellow,black,brown
slice()
//slice()能夠基於當前陣列中的一或多個項建立一個新陣列
var colors = ["red", "green", "blue", "yellow", "purple"];
var colors2 = colors.slice(1);
var colors3 = colors.slice(1,4);
alert(colors2); //green,blue,yellow,purple
alert(colors3); //green,blue,yellow
如果 slice()方法的引數中有一個負數,則用陣列長度加上該數來確定相應的位置。例如,在一個包含 5 項的陣列上呼叫 slice(-2,-1)與呼叫 slice(3,4)得到的結果相同。如果結束位置小於起始位置,則返回空陣列。
splice()
var colors = ["red", "green", "blue"];
var removed = colors.splice(0,1); // 刪除第一項
alert(colors); // green,blue
alert(removed); // red,返回的陣列中只包含一項
removed = colors.splice(1, 0, "yellow", "orange"); // 從位置 1 開始插入兩項
alert(colors); // green,yellow,orange,blue
alert(removed); // 返回的是一個空陣列
removed = colors.splice(1, 1, "red", "purple"); // 插入兩項,刪除一項
alert(colors); // green,red,purple,orange,blue
alert(removed); // yellow,返回的陣列中只包含一項
位置方法
indexOf()、lastIndexOf()
//全等操作符
var numbers = [1,2,3,4,5,4,3,2,1];
alert(numbers.indexOf(4)); //3
alert(numbers.lastIndexOf(4)); //5
alert(numbers.indexOf(4, 4)); //5
alert(numbers.lastIndexOf(4, 4)); //3
var person = { name: "Nicholas" };
var people = [{ name: "Nicholas" }];
var morePeople = [person];
alert(people.indexOf(person)); //-1
alert(morePeople.indexOf(person)); //0
迭代方法
every():
//every():對陣列中的每一項執行給定函式,如果該函式對每一項都返回 true,則返回 true。
var numbers = [1,2,3,4,5,4,3,2,1];
var everyResult = numbers.every(function(item, index, array){
return (item > 2);
});
alert(everyResult); //false
filter()
//filter():對陣列中的每一項執行給定函式,返回該函式會返回 true 的項組成的陣列。
var numbers = [1,2,3,4,5,4,3,2,1];
var filterResult = numbers.filter(function(item, index, array){
return (item > 2);
});
alert(filterResult); //[3,4,5,4,3]
forEach()
//forEach():對陣列中的每一項執行給定函式。這個方法沒有返回值。
var numbers = [1,2,3,4,5,4,3,2,1];
numbers.forEach(function(item, index, array){
//執行某些操作
});
map()
//map():對陣列中的每一項執行給定函式,返回每次函式呼叫的結果組成的陣列。
var numbers = [1,2,3,4,5,4,3,2,1];
var mapResult = numbers.map(function(item, index, array){
return item * 2;
});
alert(mapResult); //[2,4,6,8,10,8,6,4,2]
some()
//some():對陣列中的每一項執行給定函式,如果該函式對任一項返回 true,則返回 true。
var numbers = [1,2,3,4,5,4,3,2,1];
var someResult = numbers.some(function(item, index, array){
return (item > 2);
});
alert(someResult); //true
歸併方法
這個函式返回的任何值都會作為第一個引數自動傳給下一項。第一次迭代發生在陣列的第二項上,因此第一個引數是陣列的第一項,第二個引數就是陣列的第二項。
reduce()
//reduce()
var values = [1,2,3,4,5];
var sum = values.reduce(function(prev, cur, index, array){
return prev + cur;
});
alert(sum); //15=(((1+2)+3)+4)+5
reduceRight()
//reduceRight()
var values = [1,2,3,4,5];
var sum = values.reduceRight(function(prev, cur, index, array){
return prev + cur;
});
alert(sum); //15=(((5+4)+3)+2)+1
Date型別
ECMAScript 中的 Date 型別是在早期 Java 中的 java.util.Date 類基礎上構建的。為此, Date型別使用自 UTC (Coordinated Universal Time,國際協調時間) 1970 年 1 月 1 日午夜(零時)開始經過的毫秒數來儲存日期。在使用這種資料儲存格式的條件下, Date 型別儲存的日期能夠精確到 1970 年 1月 1 日之前或之後的 285 616 年。
//建立時間物件
var now = new Date();
Date.parse()
//Date.parse()方法接收一個表示日期的字串引數,然後嘗試根據這個字串返回相應日期的毫秒數。
var someDate = new Date(Date.parse("May 25, 2004"));//美國
var someDate = new Date("May 25, 2004");
Date.UTC()
//Date.UTC()方法同樣也返回表示日期的毫秒數
/ GMT 時間 2000 年 1 月 1 日午夜零時
var y2k = new Date(Date.UTC(2000, 0));
// GMT 時間 2005 年 5 月 5 日下午 5:55:55
var allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55));
// 本地時間 2000 年 1 月 1 日午夜零時
var y2k = new Date(2000, 0);
// 本地時間 2005 年 5 月 5 日下午 5:55:55
var allFives = new Date(2005, 4, 5, 17, 55, 55);
Data.now()
//Data.now(),返回表示呼叫這個方法時的日期和時間的毫秒數。
//取得開始時間
var start = Date.now();
//呼叫函式
doSomething();
//取得停止時間
var stop = Date.now(),
result = stop – start;
繼承的方法
Date 型別的 toLocaleString()方法會按照與瀏覽器toString()方法則通常返回帶有時區資訊的日期和時間,其中時間一般以軍用時間(即小時的範圍是 0 到 23)表示。設定的地區相適應的格式返回日期和時間。valueOf()方法,則根本不返回字串,而是返回日期的毫秒錶示。
var date1 = new Date(2007, 0, 1); //"January 1, 2007"
var date2 = new Date(2007, 1, 1); //"February 1, 2007"
alert(date1 < date2); //true
alert(date1 > date2); //false
日期格式化方法
Date 型別還有一些專門用於將日期格式化為字串的方法,這些方法如下。
toDateString()——以特定於實現的格式顯示星期幾、月、日和年;
toTimeString()——以特定於實現的格式顯示時、分、秒和時區;
toLocaleDateString()——以特定於地區的格式顯示星期幾、月、日和年;
toLocaleTimeString()——以特定於實現的格式顯示時、分、秒;
toUTCString()——以特定於實現的格式完整的 UTC 日期。
日期/時間元件方法
RegExp 型別
ECMAScript 通過 RegExp 型別來支援正則表示式。
//建立一個正則表示式
var expression = / pattern / flags ;
標誌 | 說明 |
g | 表示全域性(global)模式,即模式將被應用於所有字串,而非在發現第一個匹配項時立即停止 |
i | 表示不區分大小寫(case-insensitive)模式,即在確定匹配項時忽略模式與字串的大小寫 |
m | 表示多行(multiline)模式,即在到達一行文字末尾時還會繼續查詢下一行中是否存在與模式匹配的項 |
字面量形式
/*
* 匹配字串中所有"at"的例項
*/
var pattern1 = /at/g;
/*
* 匹配第一個"bat"或"cat",不區分大小寫
*/
var pattern2 = /[bc]at/i;
/*
* 匹配所有以"at"結尾的 3 個字元的組合,不區分大小寫
*/
var pattern3 = /.at/gi;
與其他語言中的正則表示式類似,模式中使用的所有元字元都必須轉義。正則表示式中的元字元包括:( [ { \ ^ $ | ) ? * + .]}
RegExp 建構函式
/*
* 匹配第一個"bat"或"cat",不區分大小寫
*/
var pattern1 = /[bc]at/i;
/*
* 與 pattern1 相同,只不過是使用建構函式建立的
*/
var pattern2 = new RegExp("[bc]at", "i");
由於 RegExp 建構函式的模式引數是字串,所以在某些情況下要對字元進行雙重轉義。所有元字元都必須雙重轉義,那些已經轉義過的字元也是如此,例如\n(字元\在字串中通常被轉義為\\,而在正則表示式字串中就會變成\\\\)。
ECMAScript 5 明確規定,使用正則表示式字面量必須像直接呼叫 RegExp 建構函式一樣,每次都建立新的 RegExp 例項。
//實際上只為/cat/建立了一個 RegExp 例項。由於例項屬性不會重置,所以在迴圈中再次呼叫 test()方法會失敗。
var re = null,
i;
for (i=0; i < 10; i++){
re = /cat/g;
re.test("catastrophe");//
}
//每次迭代都會建立一個新的RegExp 例項,所以每次呼叫 test()都會返回 true。
for (i=0; i < 10; i++){
re = new RegExp("cat", "g");
re.test("catastrophe");
}
RegExp例項屬性
RegExp 的每個例項都具有下列屬性,通過這些屬性可以取得有關模式的各種資訊。
global:布林值,表示是否設定了 g 標誌。
ignoreCase:布林值,表示是否設定了 i 標誌。
lastIndex:整數,表示開始搜尋下一個匹配項的字元位置,從 0 算起。
multiline:布林值,表示是否設定了 m 標誌。
source:正則表示式的字串表示,按照字面量形式而非傳入建構函式中的字串模式返回。
var pattern1 = /\[bc\]at/i;
alert(pattern1.global); //false
alert(pattern1.ignoreCase); //true
alert(pattern1.multiline); //false
alert(pattern1.lastIndex); //0
alert(pattern1.source); //"\[bc\]at"
var pattern2 = new RegExp("\\[bc\\]at", "i");
alert(pattern2.global); //false
alert(pattern2.ignoreCase); //true
alert(pattern2.multiline); //false
alert(pattern2.lastIndex); //0
alert(pattern2.source); //"\[bc\]at"
RegExp例項方法
RegExp 物件的主要方法是 exec(),該方法是專門為捕獲組而設計的。 exec()接受一個引數,即要應用模式的字串,然後返回包含第一個匹配項資訊的陣列;或者在沒有匹配項的情況下返回 null。返回的陣列雖然是 Array 的例項,但包含兩個額外的屬性: index 和 input。其中, index 表示匹配項在字串中的位置,而 input 表示應用正則表示式的字串。在陣列中,第一項是與整個模式匹配的字串,其他項是與模式中的捕獲組匹配的字串(如果模式中沒有捕獲組,則該陣列只包含一項)。
var text = "mom and dad and baby";
var pattern = /mom( and dad( and baby)?)?/gi;
var matches = pattern.exec(text);
alert(matches.index); // 0
alert(matches.input); // "mom and dad and baby"
alert(matches[0]); // "mom and dad and baby"
alert(matches[1]); // " and dad and baby"
alert(matches[2]); // " and baby"
exec()
var text = "cat, bat, sat, fat";
var pattern1 = /.at/;
var matches = pattern1.exec(text);
alert(matches.index); //0
alert(matches[0]); //cat
alert(pattern1.lastIndex); //0
matches = pattern1.exec(text);
alert(matches.index); //0
alert(matches[0]); //cat
alert(pattern1.lastIndex); //0
var pattern2 = /.at/g;
var matches = pattern2.exec(text);
alert(matches.index); //0
alert(matches[0]); //cat
alert(pattern2.lastIndex); //3
matches = pattern2.exec(text);
alert(matches.index); //5
alert(matches[0]); //bat
alert(pattern2.lastIndex); //8
test()
var text = "000-00-0000";
var pattern = /\d{3}-\d{2}-\d{4}/;
if (pattern.test(text)){
alert("The pattern was matched.");
}
toLocaleString()和 toString()
var pattern = new RegExp("\\[bc\\]at", "gi");
alert(pattern.toString()); // /\[bc\]at/gi
alert(pattern.toLocaleString()); // /\[bc\]at/gi
正則表示式的 valueOf()方法返回正則表示式本身。
RegExp建構函式屬性
var text = "this has been a short summer";
var pattern = /(.)hort/g;
/*
* 注意: Opera 不支援 input、 lastMatch、 lastParen 和 multiline 屬性
* Internet Explorer 不支援 multiline 屬性
*/
if (pattern.test(text)){
alert(RegExp.input); // this has been a short summer
alert(RegExp.leftContext); // this has been a
alert(RegExp.rightContext); // summer
alert(RegExp.lastMatch); // short
alert(RegExp.lastParen); // s
alert(RegExp.multiline); // false
}
模式的侷限性
ECMAScript 正則表示式不支援的特性:
匹配字串開始和結尾的\A 和\Z 錨①
向後查詢(lookbehind) ②
並集和交集類
原子組(atomic grouping)
Unicode 支援(單個字元除外,如\uFFFF)
命名的捕獲組③
s(single,單行)和 x(free-spacing,無間隔)匹配模式
條件匹配
正則表示式註釋