本章內(nèi)容
- 使用對象
- 創(chuàng)建并操作數(shù)組
- 理解基本的 JavaScript 類型
- 使用基本類型和基本包裝類型
引用類型的值(對象)是引用類型的一個實例。
雖然引用類型與類看起來相似,但它們并不是相同的概念。為避免混淆,本書將不使用類這個概念。
新對象是使用new
操作符跟一個構(gòu)造函數(shù)來創(chuàng)建的。
var person = new Object();
這行代碼創(chuàng)建了Object
引用類型的一個新實例,然后把該實例保存在了變量person
中。使用的構(gòu)造函數(shù)是Object
,它只為新對象定義了默認(rèn)的屬性和方法。
5.1 Object 類型
創(chuàng)建Object
實例的方式有兩種。第一種是使用new
操作符后跟Object
構(gòu)造函數(shù)。
var person = new Object();
person.name = "Nicholas";
person.age = 29;
另一種是使用對象字面量表示法。
var person = {
name : "Nicholas",
age : 29
}
在使用對象字面量語法時,屬性名也可以使用字符串。
var person = {
"name" : "Nicholas",
"age" : 29,
5: true
}
這個例子會創(chuàng)建一個對象,包含三個屬性:name
、age
、5
。但這里的數(shù)值屬性會自動轉(zhuǎn)換為字符串。
另外,使用對象字面語法時,如果留空其花括號,則可以定義只包含默認(rèn)屬性和方法的對象。
var person = {}; //與new Object()相同
person.name = "Nicholas";
person.age = 29;
開發(fā)人員更青睞對象字面量語法。實際上,對象字面量也是向函數(shù)傳遞大量可選參數(shù)的首選方式。
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"
});
這種傳遞參數(shù)的模式最適合需要向函數(shù)傳入大量可選參數(shù)的情形。
一般來說,訪問對象屬性時使用的都是點表示法,這也是很多面向?qū)ο笳Z言中通用的語法。在JavaScript也可以使用方括號表示來訪問對象的屬性。使用方括號語法時,應(yīng)該將要訪問的屬性以字符串形式放在方括號中。
alert(person["name"]); //"Nicholas"
alert(person.name); //"Nicholas"
從功能上看,這兩種訪問對象屬性的方法沒有任何區(qū)別。但方括號語法的主要優(yōu)點是可以通過變量來訪問屬性。
var propertyName = "name";
alert(person[propertyName]); //"Nicholas"
通常,除非必須使用變量來訪問屬性,否則我們建議使用點表示法。
5.2 Array 類型
ECMAScript 中的數(shù)組與其他多數(shù)語言中的數(shù)組有著相當(dāng)大的區(qū)別。雖然 ECMAScript 數(shù)組與其他語言中的數(shù)組都是數(shù)據(jù)的有序列表,但與其他語言不同的是,ECMAScript 數(shù)組的每一項可以保存任何類型的數(shù)據(jù)。而且,ECMAScript 數(shù)組的大小是可以動態(tài)調(diào)整的,即可以隨著數(shù)據(jù)的添加自動增長以容納新增數(shù)據(jù)。
創(chuàng)建數(shù)組的基本方式有兩種。第一種是使用Array
構(gòu)造函數(shù)。
var colors = new Array();
如果預(yù)先知道數(shù)組要保存的項目數(shù)量,也可以給構(gòu)造函數(shù)傳遞該數(shù)量,而該數(shù)量會自動變成length
屬性的值。
var colors = new Array(20);
也可以向Array
構(gòu)造函數(shù)傳遞數(shù)組中應(yīng)該包含的項。
var colors = new Array("red", "blue", "green");
傳遞一個值也可以創(chuàng)建數(shù)組。
var colors = new Array(3); //創(chuàng)建一個包含3項的數(shù)組
var names = new Array("Greg"); //創(chuàng)建一個包含1項,即字符串“Greg”的數(shù)組
創(chuàng)建數(shù)組的第二種基本方式是使用數(shù)組字面量表示法。
var colors = ["red", "blue", "green"];
var names = [];
與對象一樣,在使用數(shù)組字面量表示法時,也不會調(diào)用
Array
構(gòu)造函數(shù)。
var colors = ["red", "blue", "green"];
alert(colors[0]);
colors[2] = "black"; //修改第三項
colors[3] = "brown"; //新增第四項
數(shù)組的項數(shù)保存在其length
屬性中,這個屬性始終返回0或更大的值。
var colors = ["red", "blue", "green"];
var names = [];
alert(colors.length); //3
alert(names.length); //0
數(shù)組的length
屬性不是只讀的。通過設(shè)置這個屬性,可以從數(shù)組的末尾移除或向數(shù)組中添加新項。
var colors = ["red", "blue", "green"];
colors.length = 2;
alert(colors[2]); //undefined
利用length
屬性也可以方便地在數(shù)組末尾添加新項。
var colors = ["red", "blue", "green"];
colors[colors.length] = "black";
colors[colors.length] = "brown";
當(dāng)把一個值放在超出當(dāng)前數(shù)組大小的位置上時,數(shù)組就會重新計算其長度值,即長度值等于最后一項的索引加 1。
var colors = ["red", "blue", "green"];
colors[99] = "black";
alert(colors.length); //100
數(shù)組位置 3 到位置 98 實際上都是不存在的,所以訪問它們都將返回undefined
。
數(shù)組最多可以包含 4294967295 個項,這幾乎已經(jīng)能夠滿足任何編程需求了。
5.2.1 檢測數(shù)組
ECMAScript 5 新增了Array.isArray()
方法。這個方法的目的是最終確定某個值到底是不是數(shù)組,而不管它是在哪個全局執(zhí)行環(huán)境中創(chuàng)建的。
if (Array.isArray(value)) {
//對數(shù)組執(zhí)行某些操作
}
5.2.2 轉(zhuǎn)換方法
所有方法都具有toLocalString()
、toString()
、valueOf()
方法。其中,調(diào)用數(shù)組的toString()
方法會返回由數(shù)組中每個值得字符串形式拼接而成的一個以逗號分隔的字符串。而調(diào)用valueOf()
返回的還是數(shù)組。實際上,為了創(chuàng)建這個字符串會調(diào)用數(shù)組每一項的toString()
方法。
var colors = ["red", "blur", "green"];
alert(colors.toString()); //red,blue,green
alert(colors.valueOf()); //red,blue,green
alert(colors); //red,blue,green
最后一行代碼直接將數(shù)組傳遞給了alert()
。由于alert()
要接收字符串參數(shù),所以它會在后臺調(diào)用toString()
方法,由此會得到與直接調(diào)用toString()
方法相同的結(jié)果。
另外,toLocaleString()
方法經(jīng)常也會返回前兩個方法相同的值。與前兩個方法唯一不同之處在于,這一次為了取得每一項的值,調(diào)用的是每一項的toLocaleString()
方法,而不是toString()
方法。
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()
方法,則可以使用不同的分隔符來構(gòu)建這個字符串。join()
方法只接收一個參數(shù),即用作分隔符的字符串,然后返回包含所有數(shù)組項的字符串。如果不給join()
方法傳入任何值,或者給它傳入undefined
,則使用逗號作為分隔符。
var colors = ["red", "green", "blue"];
alert(colors.join(",")); //red,green,blue
alert(colors.join("||")); //red||green||blue
如果數(shù)組中的某一項的值是
null
或者undefined
,那么該值在join()
、toLocaleString()
、toString()
、valueOf()
方法返回的結(jié)果以空白字符串表示。
5.2.3 棧方法
ECMAScript 為數(shù)組專門提供了push()
和pop()
方法,以便實現(xiàn)類似棧的行為。
push()
方法可以接收任意數(shù)量的參數(shù),把它們逐個添加到數(shù)組末尾,并返回修改后數(shù)組的長度。而pop()
方法則從數(shù)組末尾移除最后一項,減少數(shù)組的length
值,然后返回移除的項。
var colors = new Array();
var count = colors.push("red", "green");
alert(count); //2
count = colors.push("black");
alert(count);
var item = colors.pop();
alert(item); //"black"
alert(colors.length); //2
5.2.4 隊列方法
棧數(shù)據(jù)結(jié)構(gòu)的訪問規(guī)則是LIFO(后進先出),而隊列數(shù)據(jù)結(jié)構(gòu)的訪問規(guī)則是FIFO(先進先出)。shift()
能夠移除數(shù)組中的第一個項并返回該項,同時將數(shù)組長度減1。結(jié)合使用shift()
和push()
方法,可以像使用隊列一樣使用數(shù)組。
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
ECMAScript還為數(shù)組提供了一個unshift()
方法。它能在數(shù)組前端添加任意個項并返回新數(shù)組的長度。因此,同時使用unshift()
和pop()
方法,可以從相反的方向來模擬隊列,即在數(shù)組的前端添加項,從數(shù)組末端移除項。
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
IE7及更早版本中其
unshift()
方法總是返回undefined
值。
5.2.5 重排序方法
數(shù)組中已經(jīng)存在兩個可以直接用來重排序的方法:reverse()
和sort()
。
var values = [1, 2, 3, 4, 5];
values.reverse();
alert(values); //5,4,3,2,1
在默認(rèn)情況下,sort()
方法按升序排列數(shù)組項。sort()
方法會調(diào)用每個數(shù)組項的toString()
轉(zhuǎn)型方法,然后比較得到的字符串,以確定如何排序。
var values = [0, 1, 5, 10, 15];
values.sort();
alert(values); //0,1,10,15,5
可見,即使例子中值得順序沒有問題,但sort()
方法會根據(jù)測試字符串的結(jié)果改變原來的順序。字符串比較時,“10”位于“5”的前面。sort()
方法可以接收一個比較函數(shù)作為參數(shù),以便我們指定那個值位于那個值的前面。
以下就是一個簡單的比較函數(shù):
function compare(value, value) {
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
也可以通過比較函數(shù)產(chǎn)生降序排序的結(jié)果,只要交換比較函數(shù)返回的值即可。
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); //15,10,5,1,0
對于數(shù)值類型或者其valueOf()
方法會返回數(shù)值類型的對象類型,可以使用一個更簡單的比較函數(shù)。這個函數(shù)只要用第二個值減第一個值即可。
function compare(value1, value2) {
return value2 - value1;
}
5.2.6 操作方法
concat()
方法可以基于當(dāng)前數(shù)組中的所有項創(chuàng)建一個新數(shù)組。具體來說,這個方法會先創(chuàng)建當(dāng)前數(shù)組一個副本,然后將接收到的參數(shù)添加到這個副本的末尾,最后返回新構(gòu)建的數(shù)組。在沒有給concat()
方法傳遞參數(shù)的情況下,它只是復(fù)制當(dāng)前數(shù)組并返回副本。如果傳遞給concat()
方法的是一或多個數(shù)組,則該方法會將這些數(shù)組中的每一項都添加到結(jié)果數(shù)組中。如果傳遞的值不是數(shù)組,這些值就會被簡單地添加到結(jié)果數(shù)組的末尾。下面來看一個例子。
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()
能夠基于當(dāng)前數(shù)組中的一或多個項創(chuàng)建一個新數(shù)組。slice()
方法可以接受一或兩個參數(shù),即要返回項的起始和結(jié)束位置。若只有一個參數(shù),slice()
方法返回從該參數(shù)指定位置開始到當(dāng)前數(shù)組末尾的所有項。如果有兩個參數(shù),該方法返回起始和結(jié)束位置之間的項——但不包括結(jié)束位置的項。注意,slice()
方法不會影響原始數(shù)組。
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()
方法的參數(shù)中有一個負(fù)數(shù),則用數(shù)組長度加上該數(shù)來確定相應(yīng)的位置。例如,在一個包含5項的數(shù)組上調(diào)用slice(-2,-1)
與調(diào)用slice(3,4)的到的結(jié)果相同。如果結(jié)束位置小于起始位置,則返回空數(shù)組。
splice()
方法的主要用途是向數(shù)組的中部插入項,但使用這種方法的方式則有如下3種。
- 刪除: 可以刪除任意數(shù)量的項,只需指定2個參數(shù):要刪除的第一項的位置和要刪除的項數(shù)。例如,
splice(0,2)
會刪除數(shù)組中的前兩項。 - 插入:可以向指定位置插入任意數(shù)量的項,只需提供3個參數(shù):起始位置、0(要刪除的項數(shù))和要插入的項。如果要插入多個項,可以再傳入第四、第五,以至任意多個項。例如,
splice(2,0,"red","green")
會從當(dāng)前數(shù)組的位置2開始插入字符串“red”和“green”。 - 替換: 可以向指定位置插入任意數(shù)項的項,且同時刪除任意數(shù)量的項,只需指定3個參數(shù):起始位置、要刪除的項數(shù)和要插入的任意數(shù)量的項。插入的項數(shù)不必與刪除的項數(shù)相等。例如,
splice(2,1,"red","green")
會刪除當(dāng)前數(shù)組位置2的項,然后自從位置2開始插入字符串“red”和“green”。
splice
方法始終都會返回一個數(shù)組,該數(shù)組中包含從原始數(shù)組中刪除的項(如果沒有刪除任何項,則返回一個空數(shù)組)。下面的代碼展示了上述3種使用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,yellow,orange,blue
alert(removed); //返回的是一個空數(shù)組
removed = colors.splice(1, 1, "red", "purple"); //插入兩項,刪除一項
alert(colors); //green,red,purple,orange,blue
alert(removed); //yellow, 返回的數(shù)組中只包含一項
5.2.7 位置方法
ECMAScript5 為數(shù)組實例添加了兩個位置方法: indexOf()
和lastIndexOf()
。這兩個方法都接收兩個參數(shù):要查找的項和(可選的)表示查找起點位置的索引。indexOf()
方法從數(shù)組的開頭(位置0)開始向后查找。lastIndexOf()
方法則從數(shù)組的末尾開始向前查找。
這倆方法都返回要查找的項在數(shù)組中的位置,或者在沒找到的情況下返回-1.在比較第一個參數(shù)與數(shù)組中的每一項時,會使用全等操作符。
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
var person = {name: "Nicholas"};
var people = [{name: "Nicholas"}];
var morePeople = [person];
alert(people.indexOf(person)); //-1
alert(morePeople.indexOf(person)); //0
5.2.8 迭代方法
ECMAScript5 為數(shù)組定義了5個迭代方法。每個方法都接收兩個參數(shù):要在每一項上運行的函數(shù)和(可選的)運行該函數(shù)的作用域?qū)ο蟆绊?code>this的值。傳入這些方法中的函數(shù)會接收三個參數(shù):數(shù)組項的值、該項在數(shù)組中的位置和數(shù)組對象本身。
-
every()
:對數(shù)組中的每一項運行給定函數(shù),如果該函數(shù)對每一項都返回true
,則返回true
。 -
filter()
:對數(shù)組中的每一項運行給定函數(shù),返回該函數(shù)會返回true
的項組成的數(shù)組。 -
forEach()
:對數(shù)組中的每一項運行給定函數(shù)。這個方法無返回值。 -
map()
:對數(shù)組中的每一項運行給定函數(shù),返回每次函數(shù)調(diào)用的結(jié)果組成的數(shù)組。 -
some()
:對數(shù)組中的每一項運行給定函數(shù),如果該函數(shù)對任一項返回true
,則返回true
。
以上方法都不會修改數(shù)組中的包含的值。
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
var someResult = numbers.some(function(item, index, array) {
return (item > 2);
});
alert(someResult); //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]
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]
forEach()
這個方法沒有返回值,只是對數(shù)組中的每一項運行傳入的函數(shù)本質(zhì)上與使用for
循環(huán)迭代數(shù)組一樣。
var numbers = [1,2,3,4,5,4,3,2,1];
numbers.forEach(function(item, index, array) {
//執(zhí)行某些操作
});
5.2.9 縮小方法
ECMAScript 5 新增了倆縮小數(shù)組的方法:reduce()
和reduceRight
。這倆方法都會迭代數(shù)組的所有想,然后構(gòu)建一個最終返回的值。其中,reduce()
方法從數(shù)組的第一項開始,逐個遍歷到最后。而reduceRight()
則從數(shù)組的最后一項開始,向前遍歷到第一項。
這倆方法都接收兩個參數(shù):一個在每一項調(diào)用的函數(shù)和(可選)作為縮小基礎(chǔ)的初始值。傳給reduce()
和reduceRight()
的函數(shù)接收 4 個參數(shù):前一個值、當(dāng)前項、項的索引和數(shù)組對象。這個函數(shù)返回的任何值都會作為第一個參數(shù)自動傳給下一項。第一次迭代發(fā)生在數(shù)組的第二項,因此第一個參數(shù)是數(shù)組的第一項,第二個參數(shù)就是數(shù)組的第二項。
使用reduce()
方法可以執(zhí)行求數(shù)組中所有值之和的操作。
var values = [1,2,3,4,5];
var sum = values.reduce(function(prev, cur, index, array) {
return prev + cur;
});
alert(sum); //15
var values = [1,2,3,4,5];
var sum = values.reduceRight(function(prev, cur, index, array) {
return prev + cur;
});
alert(sum); //15
5.3 Date 類型
Date
類型使用自 UTC 1970 年 1 月 1 日 零時開始經(jīng)過的毫秒數(shù)來保存日期。
使用new
操作符和Date
構(gòu)造函數(shù)即可。
var now = new Date();
如果想根據(jù)特定的日期和時間創(chuàng)建日期對象,必須傳入表示該日期的毫秒數(shù)。為了簡化計算過程,提供了倆方法:Date.parse()
和Date.UTC()
。
Date.parse()
方法接收一個表示日期的字符串參數(shù),然后嘗試根據(jù)這個字符串返回相應(yīng)日期的毫秒數(shù)。
如果傳入的字符串不能表示日期,那么它會返回NaN
。實際上,如果直接將表示日期的字符串傳遞給Date
構(gòu)造函數(shù),也會在后臺調(diào)用Date.parse()
。
var someDate = new Date("May 25, 2004");
Date.UTC()
方法同樣返回表示日期的毫秒數(shù),但它與Date.parse()
在構(gòu)建時使用不同的信息。參數(shù)分別是年份、基于0的月份,月中的哪一天、小時數(shù)(0到23)、分鐘、秒以及毫秒數(shù)。這些參數(shù)中,只有前兩個參數(shù)是必須的。如果沒有提供月中天數(shù),擇假設(shè)天數(shù)為1;如果省略其他參數(shù),則統(tǒng)統(tǒng)假設(shè)為0。
var y2k = new Date(Date.UTC(2000, 0));
var allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55));
Date
構(gòu)造函數(shù)也會模仿Date.UTC()
,但有一點明顯不同:日期和時間都基于本地時區(qū)而非GMT來創(chuàng)建。
ECMAScript 5 添加了Date.now()
方法,返回表示調(diào)用這個方法時的日期和時間的毫秒數(shù)。這個方法簡化了使用Date
對象分析代碼的工作。
var start = Date.now();
doSomething();
var stop = Date.now(),
result = stop - start;
5.3.1 繼承的方法
與其他引用類型一樣,Date
類型也重寫了toLocaleString()
、toString()
和valueOf()
方法;但這些方法返回的值與其他類型中的方法不同。Date
類型的 toLocaleString()
方法會按照與瀏覽器設(shè)置的地區(qū)相適應(yīng)的格式返回日期和時間。而toString()
方法則通常會返回帶有時區(qū)信息的日期和時間,其中時間一般以軍用時間(0到23)表示。
至于Date
類型的valueOf()
方法,則根本不返回字符串,而是返回日期的毫秒表示。因此,可以方便使用比較操作符來比較日期值。
var date1 = new Date(2007, 0, 1);
var date2 = new Date(2007, 1, 1);
alert(date1 < date2); //true
alert(date1 > date2); //false
5.3.2 日期格式化方法
Date
類型還有一些專門用于將日期格式化為字符串的方法。
-
toDateString()
——以特定于實現(xiàn)的格式顯示星期幾、月、日和年; -
toTimeString()
——以特定于實現(xiàn)的格式顯示時、分、秒和時區(qū); -
toLocaleDateString()
——以特定于地區(qū)的格式顯示星期幾、月、日和年; -
toLocaleTimeString()
——以特定于實現(xiàn)的格式顯示時、分、秒; -
toUTCString()
——以特定于實現(xiàn)的格式完整的UTC日期。
以上這些字符串格式方法的輸出也是因瀏覽器而異的,因此沒有哪一個方法能夠用來在用戶界面中顯示一致的日期信息。
5.3.3 日期/時間組件方法
方法 | 說明 |
---|---|
getTime() | 返回表示日期的毫秒數(shù);與valueOf() 方法返回的值相同 |
setTime(毫秒) | 以毫秒數(shù)設(shè)置日期,會改變整個日期 |
getFullYear() | 取的4位數(shù)的年份 |
getUTCFullYear() | 返回UTC日期的4位數(shù)年份 |
getMonth() | 返回日期的月份,其中0表示一月 |
getUTCMonth() | 。。。 |
setMonth(月) | 設(shè)置日期的月份,必須大于0,超過11增加年份 |
setUTCMonth(月) | |
getDate() | 返回日期月份中的天數(shù) |
getUTCDate() | |
setDate(日) | 設(shè)置日期月份中的天數(shù)。如果傳入的值超過了該月中應(yīng)有的天數(shù),則增加月份 |
setUTCDate() | |
getDay() | 返回日期中星期的星期幾(其中0表示星期日,6表示星期六) |
getUTCDay() | |
getHours() | 返回日期中的小時數(shù)(0到23) |
getUTCHours() | |
setHours(時) | 設(shè)置日期中的小時數(shù)。傳入的值超過了23則增加月份中的天數(shù) |
setUTCHours(時) | |
getMinutes() | 返回日期中的分鐘數(shù) |
getUTCMinutes() | |
setMinutes(分) | 設(shè)置日期中的分鐘數(shù)。傳入的值超過59則增加小時數(shù) |
setUTCMinutes(分) | |
getSeconds() | 返回日期中的秒數(shù) |
getUTCSeconds() | |
setSeconds(秒) | 設(shè)置日期中的秒數(shù)。傳入的值超過了59會增加分鐘數(shù) |
setUTCSeconds(秒) | |
getMilliseconds() | 返回日期中的毫秒數(shù) |
getUTCMilliseconds() | |
setMilliseconds(毫秒) | 設(shè)置日期中的毫秒數(shù) |
setUTCMilliseconds(毫秒) | |
getTimezoneOffset() | 返回本地時間與UTC時間相差的分鐘數(shù)。 |
5.4 RegExp 類型
ECMAScript通過RegExp
類型來支持正則表達(dá)式。
var expression = / pattern / flags ;
其中的模式(pattern)部分可以是任何簡單或復(fù)雜的正則表達(dá)式,可以包含字符類、限定類、分組、向前查找以及反向引用。每個正則表達(dá)式都可帶有一或多個標(biāo)志(flags),用以標(biāo)明正則表達(dá)式的行為。正則表達(dá)式的匹配模式支持下列3個標(biāo)志。
- g: 表示全局模式,即模式將被應(yīng)用于所有字符串,而非在發(fā)現(xiàn)第一個匹配項時立即停止;
- i:表示不區(qū)分大小寫模式,即再確定匹配時忽略模式與字符串的大小寫;
- m:表示多行模式,即在到達(dá)一行文本末尾時還會繼續(xù)查找下一行中是否存在與模式匹配的項。
因此,一個正則表達(dá)式就是一個模式與上述3個標(biāo)志的組合體。不同組合產(chǎn)生不同結(jié)果。
//匹配字符串中所有“at”的實例
var pattern1 = /at/g;
//匹配第一個“bat”或“cat”,不區(qū)分大小寫
var pattern2 = /[bc]at/i;
//匹配所有以“at”結(jié)尾的3個字符的組合,不區(qū)分大小寫
var pattern3 = /.at/gi;
與其他元字符在正則表達(dá)式中都有一或多種特殊用途,因此如果想要匹配字符串中包含的這些字符,就必須對它們進行轉(zhuǎn)義。
另一種創(chuàng)建正則表達(dá)式的方式是使用RegExp
構(gòu)造函數(shù),它接收兩個參數(shù):一個是要匹配的字符串模式,另一個是可選的標(biāo)志字符串。
var pattern1 = /[bc]at/i;
var pattern2 = new RegExp("[bc]at", "i");
要注意的是,傳遞給RegExp
構(gòu)造函數(shù)的兩個參數(shù)都是字符串。在某些情況下要對字符進行雙重轉(zhuǎn)義。所有元字符都必須雙重轉(zhuǎn)義,那些已經(jīng)轉(zhuǎn)義的字符也是如此,例如\n(字符\在字符串中通常被轉(zhuǎn)義為\,而在正則表達(dá)式字符串中就會變成\\)。下表給出了一些模式。
字面量模式 | 等價的字符串 |
---|---|
/[bc]at/ | "\[bc\]at" |
/.at/ | "\.at" |
/name/age/ | "name\/age" |
/\d.\d{1,2}/ | "\d.\d{1,2}" |
/\w\hello\123/ | "\w\\hello\\123" |
使用正則表達(dá)式字面量和使用RegExp
構(gòu)造函數(shù)創(chuàng)建的表達(dá)式不一樣。
ECMAScript 5 明確規(guī)定,使用正則表達(dá)式字面量必須像直接調(diào)用RegExp
構(gòu)造函數(shù)一樣,每次都創(chuàng)建新的RegExp
實例。IE9+、Firefox 4+ 和 Chrome 都據(jù)此做出了修改。
5.4.1 RegExp 實例屬性
RegExp
的每個實例都具有下列屬性,通過這些屬性可以取得有關(guān)模式的各種信息。
-
global
:布爾值,表示是否設(shè)置了g
標(biāo)志。 -
ignoreCase
:布爾值,表示是否設(shè)置了i
標(biāo)志。 -
lastIndex
:整數(shù),表示開始搜索下一個匹配項的字符位置,從0算起。 -
multiline
:布爾值,表示是否設(shè)置了m
標(biāo)志。 -
source
:正則表達(dá)式的字符串表示,按照字面量形式而非傳入構(gòu)造函數(shù)中的字符串模式返回。
5.4.2 RegExp 實例方法
RegExp
對象的主要方法是exec()
。exec()
接受一個參數(shù),即要應(yīng)用模式的字符串,然后返回包含第一個匹配項信息點數(shù)組;或者在沒有匹配項的情況下返回null
。返回的數(shù)組雖然是Array
的實例,但包含倆額外的屬性:index
和input
。其中,index
表示匹配在字符串中的位置,而input
表示應(yīng)用正則表達(dá)式的字符串。在數(shù)組中,第一項是與整個模式匹配的字符串,其他項是與模式中的捕獲組匹配的字符串(如果模式中沒有捕獲組,則該數(shù)組只包含一項)。
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()
方法而言,即使在模式中設(shè)置了全局標(biāo)志(g),他每次也只會返回一個一個匹配項。在設(shè)置全局標(biāo)志的情況下,每次調(diào)用exec()
則都會在字符串中繼續(xù)查找新匹配項,如下面的例子所示。
正則表達(dá)式的第二個方法是test()
,它接受一個字符串參數(shù)。在模式與該參數(shù)匹配的情況下返回true
;否則,返回false
。
RegExp
實例繼承的toLocaleString()
和toString()
方法都會返回正則表達(dá)式的字面量,于創(chuàng)建方式無關(guān)。
5.4.3 RegExp 構(gòu)造函數(shù)屬性
具體屬性略。
還有多達(dá)9個用于存儲捕獲組的構(gòu)造函數(shù)屬性。訪問這些屬性的語法是RegExp.$1、RegExp.$2...RegExp.$9
, 分別用于存儲第一,第二......第九個匹配的捕獲組。在調(diào)用exec()
或test()
方法時,這些屬性會被自動填充。
var text = "this has been a short summer";
var pattern = /(..)or(.)/g;
if(pattern.test(text)) {
alert(RegExp.$1); //sh
alert(RegExp.$2); //t
}
5.4.4 模式的局限性
下面列出了 ECMAScript 正則表達(dá)式不支持的特性。
- 匹配字符串開始和結(jié)尾的\A 和 \Z (但支持以插入符號^和美元符號$來匹配字符串的開始和結(jié)尾)
- 向后查找(但完全支持向前查找)
- 并集和交集類
- 原子組
- Unicode 支持
- 命名的捕獲組(但支持編號的捕獲組)
- s(單行)和 x(無間隔)匹配模式
- 條件匹配
- 正則表達(dá)式注釋
5.5 Function 類型
每個函數(shù)都是Function
類型的實例,而且都與其他引用類型一樣具有屬性和方法。由于函數(shù)是對象,因此函數(shù)名實際上也是一個指向函數(shù)對象的指針,不會與某個函數(shù)綁定。函數(shù)通常是使用函數(shù)聲明語法定義的。
function sum (num1, num2) {
return num1 + num2;
}
這與下面使用函數(shù)表達(dá)式定義函數(shù)的方式幾乎相差無幾
var sum = function(num1, num2) {
return num1 + num2;
};
最后一種定義函數(shù)的方式是使用Function
構(gòu)造函數(shù),不推薦。
由于函數(shù)名僅僅是指向函數(shù)的指針,因此函數(shù)名與包含對象指針的其他變量沒有什么不同。
function sum(num1, num2) {
return num1 + num2;
}
alert(sum(10, 10)); //20
var anotherSum = sum;
alert(anotherSum(10, 10)); //20
sum = null;
alert(anotherSum(10, 10)); //20
5.5.1 沒有重載(深入理解)
將函數(shù)名想象為指針,也有助于理解為什么 ECMAScript 中沒有函數(shù)重載的概念。
5.5.2 函數(shù)聲明與函數(shù)表達(dá)式
解析器會率先讀取函數(shù)聲明,并使其在執(zhí)行任何代碼之前可用(可以訪問);至于函數(shù)表達(dá)式,則必須等到解析器執(zhí)行到它所在的代碼行,才會真正被解釋執(zhí)行。
alert(sum(10, 10));
function sum(num1, num2) {
return num1 + num2;
}
以上代碼正常運行。因為在代碼執(zhí)行之前,解析器就已經(jīng)通過一個名為函數(shù)聲明提升的過程,讀取并將函數(shù)聲明添加到執(zhí)行環(huán)境中。
alert(sum(10, 10));
var sum = function(num1, num2){
return num1 + num2;
}
以上代碼在運行期間會產(chǎn)生錯誤,原因在于函數(shù)位于一個初始化語句中,而不是一個函數(shù)聲明。
作為值的函數(shù)
因為 ECMAScript 中的函數(shù)本身就是變量,所以函數(shù)也可以作為值來使用。不僅可以像傳遞參數(shù)一樣把一個函數(shù)傳遞給另一個函數(shù),而且可以將一個函數(shù)作為另一個函數(shù)的結(jié)果返回。
function callSomeFunction(someFunction, someArgument) {
return someFunction(someArgument);
}
function add10(num) {
return num + 10;
}
var result = callSomeFunction(add10, 10);
alert(result); //20
當(dāng)然,可以從一個函數(shù)中返回另一個函數(shù),而且這也是極為有用的一種技術(shù)。
function createComparisonFunction(propertyName) {
return function(object1, object2) {
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if (value1 < value2) {return -1;} else if (value1 > value2) {return1;} else {return 0'}
};
}
var data = [{name: "Zachary", age: 28}, {name: "Nicholas", age: 29}];
data.sort(createComparisonFunction("name"));
alert(data[0].name); //Nicholas
data.sort(createComparisonFunction("age"));
alert(data[0].name); //Zachary
5.5.4 函數(shù)內(nèi)部屬性
在函數(shù)內(nèi)容中,有兩個特殊的對象:arguments
和this
。其中,arguments()
是一個類數(shù)組對象,包含著傳入函數(shù)中的所有參數(shù)。雖然arguments
的主要用途是保存函數(shù)參數(shù),但這個對象還有一個名叫callee
的屬性,該屬性是一個指針,指向擁有這個arguments
對象的函數(shù)。
function factorial (num) {
if (num <=1) {
return 1;
} else {
return num * factorial(num-1)
}
}
定義階乘函數(shù)一般都要用到遞歸算法;問題是這個函數(shù)的執(zhí)行與函數(shù)名factorial
緊緊耦合在了一起。為了消除這種耦合現(xiàn)象,可以這樣使用arguments.callee
。
function factorial (num) {
if (num <=1) {
return -1;
} else {
return num * arguments.callee(num-1)
}
}
在重寫后的factorial()
函數(shù)的函數(shù)體內(nèi),沒有在引用函數(shù)名factorial
。這樣,無論引用函數(shù)時使用的是什么名字,都可以保證正常完成遞歸調(diào)用。
var trueFactorial = factorial;
factorial = function () {
return 0;
};
alert(trueFactorial(5)); //120
alert(factorial(5)); //0
函數(shù)內(nèi)部的另一個特殊對象是this
,引用的是函數(shù)據(jù)以執(zhí)行的環(huán)境對象——或者可以說是this
值(擋在網(wǎng)頁的全局作用域中調(diào)用函數(shù)時,this
對象引用的就是window
)。
window.color = "red";
var o = {color: "blue"};
function sayColor () {
alert(this.color);
}
sayColor(); //"red"
o.syaColor = sayColor;
o.sayColor(); //"blue"
請牢記,函數(shù)的名字僅僅是一個包含指針的變量而已。因此,即使是在不同的環(huán)境中執(zhí)行,全局的
sayColor()
函數(shù)與o.sayColor()
指向的仍然是同一個函數(shù)。
ECMAScript 5 也規(guī)范化了另一個函數(shù)對象的屬性:caller
。這個屬性中保存著調(diào)用當(dāng)前函數(shù)的函數(shù)的引用,如果是在全局作用域中調(diào)用當(dāng)前函數(shù),它的值為null
。
function outer() {
inner();
}
function inner() {
alert(inner.caller);
}
outer();
以上代碼會導(dǎo)致警告框中顯示outer()
函數(shù)的源代碼。因為outer()
調(diào)用了inner()
,所以inner.caller
就指向outer()
。為了實現(xiàn)更松散的耦合,也可以通過arguments.callee.caller
來訪問相同的信息。
嚴(yán)格模式下,arguments.callee
會導(dǎo)致錯誤。
5.5.5 函數(shù)屬性和方法
ECMAScript 中的函數(shù)是對象,因此函數(shù)也有屬性和方法。每個函數(shù)包含兩個屬性:length
和prototype
。其中,length
屬性表示函數(shù)希望接收的命名參數(shù)的個數(shù)。
function sayName(name) {
alert(name);
}
function sum(num1, num2) {
return num1 + num2;
}
function sayHi() {
alert("hi");
}
alert(sayName.length); //1
alert(sum.length); //2
alert(sayHi.length); //0
對于ECMAScript 中的引用類型而言,prototype
是保存它們所有實例方法的真正所在。換句話說,諸如toString()
和valueOf()
等方法實際上都保持在prototype
名下,只不過是通過各自對象的實例訪問罷了。在創(chuàng)建自定義引用類型以及實現(xiàn)繼承時,prototype
屬性的作用是極為重要的。
每個函數(shù)都包含兩個非繼承而來的方法:apply()
和call()
。這兩個方法的用途都是在特定的作用域中調(diào)用函數(shù)。實際上等于設(shè)置函數(shù)體內(nèi)this
對象的值。首先,apply()
方法接收兩個參數(shù):一個是在其中運行函數(shù)的作用域,另一個是參數(shù)數(shù)組。其中,第二個參數(shù)可以是Array
的實例,也可以是arguments
對象。
function sum(num1, num2) {
return num1 + num2;
}
function callSum1(num1, num2) {
return sum.call(this, arguments); //傳入arguments 對象
}
function callSum2(num1, num2) {
return sum.apply(this, [num1, num2]); //傳入?yún)?shù)
}
alert(callSum1(10,10)); //20
alert(callSum2(10,10)); //20
callSum1()
在執(zhí)行sum()函數(shù)時傳入了this
作為this
值(因為是在全局作用域中調(diào)用的,所以傳入的就是window
對象)和arguments
對象。而callSum2
同樣也調(diào)用了sum()
函數(shù),但它傳入的則是this
和一個參數(shù)數(shù)組。這兩個函數(shù)都會正常執(zhí)行并返回正確的結(jié)果。
在嚴(yán)格模式下,未指定環(huán)境對象而調(diào)用函數(shù),則
this
值不會轉(zhuǎn)型為window
。除非明確把函數(shù)添加到某個對象或者調(diào)用apply()
或call()
,否則this
值將是undefined
。
call()
方法與apply()
方法的作用相同,它們的區(qū)別僅在于接收參數(shù)的方式不同。對于call()
方法而言,第一個參數(shù)是this
值沒有變化,變化的是其余參數(shù)都直接傳遞給函數(shù)。即在使用call()
方法時,傳遞給函數(shù)的參數(shù)必須逐個列舉出來。
function sum(num1, num2) {
return num1 + num2;
}
function callSum(num1, num2) {
return sum.call(this, num1, num2);
}
alert(callSum(10,10)); //20
傳遞參數(shù)并非apply()
和call()
真正的用武之地;它們真正強大的地方是能夠擴充函數(shù)賴以運行的作用域。
window. color = "red";
var o = {color: "blue"};
function sayColor() {
alert(this.color);
}
sayColor(); //red
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //blue
使用call()
或apply
來擴充作用域的最大好處,就是對象不需要與方法有任何耦合關(guān)系。
ECMAScript 5 還定義了一個方法:bind()
。這個方法會創(chuàng)建一個函數(shù)的實例,其this
值會被綁定到傳給bind()
函數(shù)的值。
window.color = "red";
var o = {color: "blue"};
function sayColor() {
alert(this.color);
}
var objectSayColor = sayColor.bind(o);
objectSayColor(); //blue
每個函數(shù)繼承的toLocaleString()
和toString()
方法始終都返回函數(shù)的代碼。返回代碼的格式則因瀏覽器而異——有的返回的代碼與源代碼中的函數(shù)代碼一樣,而有的則返回函數(shù)代碼的內(nèi)部表示,即由解析器刪除了注釋并對某些代碼作了改動后的代碼。由于存在這些差異,我們無法根據(jù)這兩個方法返回的結(jié)果來實現(xiàn)任何重要功能;不過,這些信息在調(diào)試代碼時倒是很有用。另外一個繼承的valueOf()
方法同樣也只有返回函數(shù)代碼。
5.6 基本包裝類型
為了便于操作基本類型值,ECMAScript 還提供了 3 個特殊的引用類型:Boolean
,Number
和String
。這些類型與本章介紹的其他引用類型相似,但同時也具有與各自的基本類型相應(yīng)的特殊行為。實際上,每當(dāng)讀取一個基本類型值的時候,后臺就會創(chuàng)建一個對應(yīng)的基本包裝類型的對象,從而讓我們能夠調(diào)用一些方法來操作這些數(shù)據(jù)。
var s1 = "some text";
var s2 = s1.substring(2);
俺們知道,基本類型值不是對象,因而從邏輯上講它們不應(yīng)該有方法(盡管如我們所愿,它們確實有方法)。其實,為了讓我們實現(xiàn)這種直觀的操作,后臺已經(jīng)自動完成了一系列的處理。當(dāng)?shù)诙写a訪問 s1 時,訪問過程處于一種讀取模式,也就是要從內(nèi)存中讀取這個字符串的值。而在讀取模式中訪問字符串時,后臺都會自動完成下列處理。
- 創(chuàng)建
String
類型的一個實例; - 在實例上調(diào)用指定的方法;
- 銷毀這個實例。
可以將以上三個步驟想象成是執(zhí)行了下列ECMAScript代碼。
var s1 = new String("some text");
var s2 = s1.substring(2);
s1 = null;
經(jīng)過此番處理,基本的字符串值就變得跟對象一樣了。而且,上面這三個步驟也分別適用于Boolean
和Number
類型對應(yīng)的布爾值和數(shù)字值。
引用類型與基本包裝類型的主要區(qū)別就是對象的生存期。使用new
操作符創(chuàng)建的引用類型的實例,在執(zhí)行流離開當(dāng)前作用域之前都一直保存在內(nèi)存中。而自動創(chuàng)建的基本包裝類型的對象,則只存在于一行代碼的執(zhí)行瞬間,然后立即銷毀。這意味著我們不能在運行時為基本類型添加屬性和方法。
var s1 = "some text";
s1.color = "red";
alert(s1.color); //undefined
問題的原因在于第二行創(chuàng)建的String
對象在執(zhí)行第三行代碼時已經(jīng)被銷毀了。第三行代碼又創(chuàng)建自己的String
對象,而該對象沒有color
屬性。
當(dāng)然,可以顯示地調(diào)用Boolean
、Number
、String
來創(chuàng)建基本包裝類型的對象。應(yīng)該盡量避免這樣做,因為這種方法做很容易讓人分不清自己是在處理基本類型還是引用類型的值。對基本包裝類型的實例調(diào)用typeof
會返回object
,而且所有基本包裝類型的對象都會被轉(zhuǎn)換為布爾值true
。
Object
構(gòu)造函數(shù)也會像工廠方法一樣,根據(jù)傳入值的類型返回相應(yīng)基本包裝類型的實例。
var obj = new Object("some text");
alert(obj instanceof String); //true
把字符串傳給Object
構(gòu)造函數(shù),就會創(chuàng)建String
的實例;其他類似。
要注意的是,使用new
調(diào)用基本包裝類型的構(gòu)造函數(shù),與直接調(diào)用同名的轉(zhuǎn)型函數(shù)是不一樣的。
var value = "25";
var number = Number(value); //轉(zhuǎn)型函數(shù)
alert(typeof number); //"number"
var obj = new Number(value); //構(gòu)造函數(shù)
alert(typeof obj); //"object"
5.6.1 Boolean 類型
Boolean
類型是與布爾值對應(yīng)的引用類型。
var booleanObject = new Boolean(true);
Boolean
類型的實例重寫了valueOf()
方法,返回基本類型值true
或false
;重寫了toString()
方法,返回字符串“true”和“false”。用處不大,經(jīng)常造成誤解。其中最常見的問題是在布爾表達(dá)式中使用Boolean
對象。
var falseObject = new Boolean(false);
var result = falseObject && true;
alert(result); //true
var falseValue = false;
result = falseValue && true;
alert(result); //false
在布爾運算中,false && true
等于false
。但是布爾表達(dá)式中的所有對象都會被轉(zhuǎn)換為true
,因此falseObject
對象在布爾表達(dá)式中代表的是true
。
基本類型與引用類型的布爾值還有兩個區(qū)別。首先,typeof
操作符對基本類型返回"boolean",而對引用類型返回"object"。其次,由于Boolean
對象是Boolean
類型的實例,所以使用instanceof
操作符測試Boolean
對象會返回true
,而測試基本類型的布爾值則返回false
。
alert(typeof falseObject); //object
alert(typeof falseValue); //boolean
alert(falseObject instanceof Boolean); //true
alert(falseValue instanceof Boolean); //false
建議永遠(yuǎn)不要使用Boolean
對象
5.6.2 Number 類型
Number
是與數(shù)字值對應(yīng)的引用類型。要創(chuàng)建Number
對象,可以在調(diào)用Number
構(gòu)造函數(shù)時向其中傳遞相應(yīng)的數(shù)值。
var numberObject = new Number(10);
Number
類型也重寫了valueOf()
、toLocaleString()
和toString()
方法。重寫后的valueOf()
方法返回對象表示的基本類型的數(shù)值,另外兩個方法則返回字符串形式的數(shù)值。在第 3 章中介紹過,可以為toString()
方法傳遞一個表示基數(shù)的參數(shù),告訴它返回幾進制的字符串形式。
除了繼承的方法外,Number
類型還提供了一些用于將數(shù)值格式化為字符串的方法。其中,toFixed()
方法會按照指定的小數(shù)位返回數(shù)值的字符串表示。
var num = 10;
alert(num.toFixed(2)); //"10.00"
如果數(shù)值本身包含的小數(shù)位比指定的還多,那么接近的最大小數(shù)位的值就會舍入。
var num = 10.005;
alert(num.toFixed(2)); //"10.01"
另外可用于格式化數(shù)值的方法是toExponential()
,該方法返回以指數(shù)表示法(也稱 e 表示法)表示的數(shù)值的字符串形式。,接受一個參數(shù),同樣也是指定輸出結(jié)果中的小數(shù)位數(shù)。
var num = 10;
alert(num.toExponential(1)); //"1.0e+1"
如果你想得到表示某個數(shù)值的最合適的格式,就應(yīng)該使用toPrecision()
方法。
對于一個數(shù)值來說,toPrecision()
方法可能會返回固定大小 (fixed)格式,也可能返回指數(shù)(exponential)格式;具體規(guī)則是看哪種格式最合適。該方法接收一個參數(shù),即表示數(shù)值的所有數(shù)字的位數(shù)(不包括指數(shù)部分)。
var num = 99;
alert(num.toPrecision(1)); //"1e+2"
alert(num.toPrecision(2)); //"99"
alert(num.toPrecision(3)); //"99.0"
不建議直接實例化Number
類型,其他與Boolean
對象一樣。
5.6.3 String 類型
String
類型是字符串的對象包裝類型,可以像下面這樣使用String
構(gòu)造函數(shù)來構(gòu)造。
var stringObject = new String("hello world");
String
對象的方法也可以在所有基本的字符串值中訪問到。其中,繼承的valueOf()
,toLocaleString()
和toString()
方法,都返回對象所表示的基本字符串值。
String
類型的每個實例都有一個length
屬性,表示字符串中包含多個字符。
var stringValue = "hello world";
alert(stringValue.length); //11
即使字符串中包含雙字節(jié)字符(不是占一個字節(jié)的 ASCII 字符),每個字符也仍然算一個字符。
- 字符方法
兩個用于訪問字符串中特定字符的方法是:charAt()
和charCodeAt()
。這倆方法都接收一個參數(shù),即基于0的字符位置。其中,charAt()
方法以單字符字符串的形式返回給定位置的那個字符。
var stringValue = "hello world";
alert (stringValue.charAt(1)); //"e"
如果你想得到的不是字符而是字符編碼。
var stringValue = "hello world";
alert(stringValue.charCodeAt(1)); //輸出“101”
在支持的瀏覽器中,可以使用方括號加數(shù)字索引來訪問字符串中的特定字符。
var stringValue = "hello world";
alert(stringValue[1]); //"e"
- 字符串操作方法
concat()
用于將一個或多個字符串拼接起來,返回拼接得到的新字符串。
var stringValue = "hello";
var result = stringValue.concat(" world");
alert(result); //"hello world"
alert(stringValue); //"hello"
concat
方法可以接收任意多個參數(shù),也就是說,可以通過它拼接任意多個字符串。
var stringValue = "hello";
var result = stringValue.concat(" world", "!");
alert(result); //"hello world!"
alert(stringValue); //"hello"
雖然concat()
是專門用來拼接字符串的方法,但實踐中使用更多的還是加號操作符(+)。
ECMAScript 提供了三個基于子字符串創(chuàng)建新字符串的方法:slice()
、substr()
和substring()
。這三個方法都會返回被操作字符串的一個子字符串,而且也都接受一或兩個參數(shù)。第一個參數(shù)指定子字符串的開始位置,第二個參數(shù)(在指定的情況下)表示子字符串到哪里結(jié)束。具體來說,slice()
和substring()
的第二個參數(shù)指定的是字符串最后一個字符后面的位置。而substr()
的第二個參數(shù)指定的則是返回的字符個數(shù)。如果沒有傳遞第二個參數(shù),則將字符串的長度作為結(jié)束位置。這些方法同樣也不會修改字符串本身的值。
var s = "hello world";
alert(s.slice(3)); //"lo world"
alert(s.substring(3)); //"lo world"
alert(s.substr(3)); //"lo world"
alert(s.slice(3, 7)); //"lo w"
alert(s.substring(3, 7)); //"lo w"
alert(s.substr(3, 7)); //"lo worl"
在傳遞給這些方法的參數(shù)是負(fù)值的情況下,它們的行為就不盡相同了。其中,slice()
方法會將傳入的負(fù)值與字符串的長度相加,substr()
方法會將負(fù)的第一個參數(shù)加上字符串的長度,而將負(fù)的第二個參數(shù)轉(zhuǎn)換為 0。最后,substring()
方法會把所有負(fù)值參數(shù)都轉(zhuǎn)換為 0。substring()
方法會將較小的數(shù)作為開始位置,將較大的數(shù)作為結(jié)束位置。
var s = "hello world";
alert(s.slice(-3)); //"rld";
alert(s.substring(-3)); //"hello world"
alert(s.substr(-3)); //"rld"
alert(s.slice(3, -4)); //"lo w"
alert(s.substr(3, -4)); //"" (空字符串)
IE 的 JavaScript 實現(xiàn)在處理向
substr()
方法傳遞負(fù)值的情況時存在問題,它會返回原始的字符串。IE9 修復(fù)了這個問題。
- 字符串位置方法
由兩個可以從字符串中查找子字符串的方法:indexOf()
和lastIndexOf()
。這兩個方法都是從一個字符串中搜索給定的子字符串,然后返回子字符串的位置(如果沒有找到,則返回 -1)。這倆方法區(qū)別在于:indexOf()
方法從字符串的開頭向后搜索子字符串,而lastIndexOf()
方法是從字符串的末尾向前搜索子字符串。
var s = "hello world";
alert(s.indexOf("o")); //4
alert(s.lastIndexOf("o")); //7
這倆方法接收可選的第二個參數(shù),表示從字符串中的那個位置開始搜索。indexOf()
會從該參數(shù)指定的位置向后搜索,忽略該位置之前的所有字符;而lastIndexOf()
則會從指定的位置向前搜索,忽略該位置之后的所有字符。
var s = "hello world";
alert(s.indexOf("o", 6)); //7
alert(s.indexOf("o", 6)); //4
在使用第二個參數(shù)的情況下,可以通過循環(huán)調(diào)用indexOf()
或lastIndexOf()
來找到所有匹配的子字符串。
var s = "asjfjsjf;sjfjsdfjsdljfsafjsaf";
var position = new Array();
var pos = s.indexOf("a");
while (pos > -1) {
positions.push(pos);
pos = s.indexOf("a", pos + 1);
}
alert(positions);
- trim() 方法
這個方法會創(chuàng)建一個字符串的副本,刪除前置及后綴的所有空格,然后返回結(jié)果。
var s = " hello world "
var trimmed = s.trim();
alert(s); //" hello world "
alert(trimmed); //"hello world"
先進瀏覽器還支持非標(biāo)準(zhǔn)的trimLeft()
和trimRight()
方法,分別用于刪除字符串開頭和末尾的空格。
字符串大小寫轉(zhuǎn)換方法
ECMAScript 中涉及字符串大小寫轉(zhuǎn)換的方法有 4 個:toLowerCase()
、toLocaleLowerCase()
、toUpperCase()
、toLocaleUpperCase()
。字符串的模式匹配方法
第一個方法就是match()
,在字符串上調(diào)用這個方法,本質(zhì)上與調(diào)用RegExp
的exec()
方法相同。match()
方法只接受一個參數(shù),要么是一個正則表達(dá)式,要么是一個RegExp
對象。
var text = "cat, bat, sat, fat";
var pattern = /.at/;
var matches = text.match(pattern);
alert(matches.index); //0
alert(matches[0]); //"cat"
alert(pattern.lastIndex); //0
另一個用于查找模式的方法是search()
。這個方法的唯一參數(shù)與match()
方法的參數(shù)相同:由字符串或RegExp
對象指定的一個正則表達(dá)式。search()
方法返回字符串中第一個匹配項的索引;如果沒有找到匹配項,則返回 -1。而且,search()
方法始終是從字符串開頭向后查找模式。
var text = "cat, bat, sat, fat";
var pos = text.search(/at/);
alert(pos); //1
為了簡化替換子字符串的操作,ECMAScript 提供了replace()
方法。這個方法接受兩個參數(shù):第一個參數(shù)可以是一個RegExp
對象或者一個字符串(這個字符串不會被轉(zhuǎn)換成正則表達(dá)式),第二個參數(shù)可以是一個字符串或者一個函數(shù)。如果第一個參數(shù)是字符串,那么只會替換第一個字符串,要想替換所有子字符串,唯一的辦法就是提供一個正則表達(dá)式,而且要指定全局標(biāo)志。
var text = "cat, bat, sat, fat";
var result = text.replace("at", "ond");
alert(result); //"cound, bat, sat, fat"
result = text.replace(/at/g, "ond");
alert(result); //"cond, bond, aond, fond"
replace()
方法的第二個參數(shù)也可以是一個函數(shù)。在只有一個匹配項的的情況下,會向這個函數(shù)傳遞 3 個參數(shù):模式的匹配項,模式匹配項在字符串中的位置和原始字符串。在正則表達(dá)式中定義了多個捕獲組的情況下,傳遞給函數(shù)的參數(shù)依次是模式的匹配項,第一個捕獲組的匹配項,第二個捕獲組的匹配項。。。,但最后兩個參數(shù)仍然分別是模式的匹配項在字符串中的位置和原始字符串。這個函數(shù)應(yīng)該返回一個字符串,表示應(yīng)該被替換額匹配項使用函數(shù)作為replace()
方法的第二個參數(shù)可以實現(xiàn)更加精細(xì)的替換操作
function htmlEscape(text) { return text.replace(/[<>"&]/g, function(match,pos,originalText) { switch(match) { case "<": return "<"; case ">": return ">"; case "&": return "&"; case "\*": return """; } });}
最后一個與模式匹配有關(guān)的方法是split()
,這個方法可以基于指定的分隔符將一個字符串分割成多個子字符串,并將結(jié)果放在一個數(shù)組中。分隔符可以是字符串,也可以是一個RegExp
對象。split()
方法可以接受可選的第二個參數(shù),用于指定數(shù)組的大小,以確保返回的數(shù)組不會超過既定大小。
var colorText = "red,blue,green,yellow";
var colors1 = colorText.split(","); //["red","blue","green", "yellow"]
var colors2 = colorText.split(",", 2); //["red", "blue"]
var colors3 = colorsText.split(/[^\,]+/); //["", ",", ",",",", ""]
- localeCompare() 方法
與操作字符串有關(guān)的最后一個方法是localeCompare()
,這個方法比較兩個字符串,并返回下列值中的一個:
- 如果字符串在字母表中應(yīng)該排在字符串參數(shù)之前,則返回一個負(fù)數(shù)(大多數(shù)情況下是 -1, 具體的值要視實現(xiàn)而定);
- 如果字符串等于字符串參數(shù),則返回 0;
- 如果字符串在字母表中應(yīng)該排在字符串參數(shù)之后,則返回一個正數(shù)(大多數(shù)情況下是 1,具體的值同樣要視實現(xiàn)而定)。
var s = "yellow";
alert(s.localeCompare("brick")); //1
alert(s.localeCompare("yellow")); //0
alert(s.localeCompare("zoo")); //-1
最好采用函數(shù)判斷并規(guī)定返回數(shù)值。
- fromCharCode() 方法
String
構(gòu)造函數(shù)本身還有一個靜態(tài)方法:fromCharCode()
。這個方法的任務(wù)是接收一或多個字符編碼,然后將他們轉(zhuǎn)換成一個字符串。從本質(zhì)上看,這個方法與實例方法charCodeAt()
執(zhí)行的是相反的操作。
alert(String.fromCharCode(104, 101, 108, 108, 111)); //"hello"
- HTML 方法
盡量不使用這些方法。故不列出。
5.7 單體內(nèi)置對象
5.7.1 Global 對象
不屬于任何其他對象的屬性和方法,最終都是它的屬性和方法。
- URI 編碼方法
encodeURI()
和encodeURIComponent()
方法可以對 URI 進行編碼,以便發(fā)送給瀏覽器。有效的 URI 中不能包含某些字符,例如空格。
其中,encodeURI()
主要用于整個URI(例如,http://www.baidu.com/illegal value.htm),而encodeURIComponent()
主要用于對某一段(例如illegal value.htm)進行編碼。它們的主要區(qū)別在于,encodeURI()
不會對本身屬于 URI 的特殊字符進行編碼,例如冒號,正斜杠,問號和井字號;而encodeURIComponent()
則會對它發(fā)現(xiàn)的任何非標(biāo)準(zhǔn)字符進行編碼。
對應(yīng)的方法為decodeURI()
和decodeURIComponent()
。
一般來說,使用
encodeURIComponent()
方法更多,因為在實踐中更常見的是對查詢字符串參數(shù)而不是對基礎(chǔ) URI 進行編碼。
- eval() 方法
非常危險,略。 - Global 對象的屬性
下表列出了所有屬性
屬性 | 說明 |
---|---|
undefined | 特殊值 |
NaN | 特殊值 |
Infinity | 特殊值 |
Object | 構(gòu)造函數(shù) |
Array | 構(gòu)造函數(shù) |
Function | 構(gòu)造函數(shù) |
Boolean | 構(gòu)造函數(shù) |
String | 構(gòu)造函數(shù) |
Number | 構(gòu)造函數(shù) |
Date | 構(gòu)造函數(shù) |
RegExp | 構(gòu)造函數(shù) |
Error | 構(gòu)造函數(shù) |
EvalError | 構(gòu)造函數(shù) |
RangeError | 構(gòu)造函數(shù) |
ReferenceError | 構(gòu)造函數(shù) |
SyntaxError | 構(gòu)造函數(shù) |
TypeError | 構(gòu)造函數(shù) |
URIError | 構(gòu)造函數(shù) |
- window 對象
ECMAScript 雖然沒有指出如何直接訪問Global
對象,但Web
瀏覽器都是將這個全局對象作為window
對象的一部分加以實現(xiàn)的。因此,在全局作用域中聲明的所有變量和函數(shù),就都成為了widnow
對象的屬性。
5.7.2 Math 對象
Math
對象提供了輔助完成數(shù)學(xué)計算的屬性和方法。
1.Math 對象的屬性
屬性 | 說明 |
---|---|
Math.E | 自然對數(shù)的底數(shù),即常量e的值 |
Math.LN10 | 10的自然對數(shù) |
Math.LN2 | 2的自然對數(shù) |
Math.LOG2E | 以2為底e的對數(shù) |
Math.LOG10E | 以10為底e的對數(shù) |
Math.PI | π的值 |
Math.SQRT1_2 | 1/2 的平方根(即2的平方根的倒數(shù)) |
Math.SQRT2 | 2的平方根 |
2.min() 和 max() 方法
還包含許多方法,用于輔助完成簡單和復(fù)雜的數(shù)學(xué)計算。
其中,min()
和'max()'方法用于確定一組數(shù)值中的最小值和最大值。這兩個方法都可以接收任意多個數(shù)值參數(shù)。
var max =Math.max(3, 54, 32, 16);
alert(max); //54
var min = Math.min(3, 54, 32, 16);
alert(min); //3
要找到數(shù)組中的最大或最小值,可以像下面這樣使用apply()
方法。
var value = [1, 2, 3, 4, 5, 6];
var max = Math.max.apply(Math, values);
這個技巧的關(guān)鍵是把Math
對象作為apply()
的第一個參數(shù),從而正確地設(shè)置this
值。然后,可以將任何數(shù)組作為第二個參數(shù)。
3.舍入方法
將小數(shù)值舍入為整數(shù)的幾個方法:Math.ceil()
、Math.floor()
、Math.round()
。
這三個方法分別遵循下列舍入規(guī)則:
- Math.ceil()執(zhí)行向上舍入
- Math.floor()執(zhí)行向下舍入
- Math.round()執(zhí)行標(biāo)準(zhǔn)舍入,即四舍五入
4.random()方法
Math.random()
方法返回介于 0 和 1 之間隨機一個隨機數(shù),不包括 0 和 1。
Math.random()
從某個整數(shù)范圍內(nèi)隨機選擇一個值。
值 = Math.floor(Math.random() * 可能值的總數(shù) + 第一個可能的值)
如果想要選擇一個介于 2 到 10 之間的值
var num = Math.floor(Math.random() * 9 +2);
多數(shù)情況下,可以通過一個函數(shù)來計算可能值的總數(shù)和第一個可能的值。
function selectFrom(lowerValue, upperValue) {
var choices = upperValue - lowerValue + 1;
return Math.floor(Math.random() * choices + lowerValue);
}
var num = selectFrom(2, 10);
alert(num); //介于 2 和 10 之間 (包括 2 和 10)的一個數(shù)值
5.其他方法
下表列出了沒有介紹到的方法
方法 | 說明 |
---|---|
Math.abs(num) | 返回絕對值 |
Math.exp(num) | 返回Math.E的num次冪 |
Math.log(num) | 返回num的自然對數(shù) |
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的正切值 |
5.8 小結(jié)
對象在 JavaScript 中被稱為引用類型的值,而且有一些內(nèi)置的引用類型可以用來創(chuàng)建特定的對象。
- 引用類型與傳統(tǒng)面向?qū)ο蟪绦蛟O(shè)計中的類相似,但實現(xiàn)不同;
-
Object
是一個基礎(chǔ)類型,其他所有類型都從Object
繼承了基本的行為; -
Array
類型是一組值的有序列表,同時還提供了操作和轉(zhuǎn)換這些值得功能; -
Date
類型提供了有關(guān)日期和時間的信息,包括當(dāng)前日期和時間以及相關(guān)計算功能; -
RegExp
類型提供了最基本的和一些高級的正則表達(dá)式功能。
函數(shù)實際上是Function
類型的實例,因此函數(shù)也是對象;由于函數(shù)是對象,所以函數(shù)也擁有方法。
因為有了基本包裝類型,所以JavaScript
中的基本類型可以被當(dāng)作對象來訪問。三種基本包裝類型分別是:Boolean
、Number
、String
。以下是它們共同的特征:
- 每個包裝類型都映射到同名的基本類型;
- 在讀取模式下訪問基本類型值時,就會創(chuàng)建對應(yīng)的基本包裝類型的一個對象,從而方便了數(shù)據(jù)操作;
- 操作基本類型值的語句一經(jīng)執(zhí)行完畢,就會立即銷毀新創(chuàng)建的包裝對象。
在所有代碼執(zhí)行之前,作用域中就已經(jīng)存在兩個內(nèi)置對象:Global
和Math
。Web 瀏覽器實現(xiàn)了承擔(dān)該角色的window
對象。全局變量和函數(shù)都是Global
對象的屬性。Math
對象提供了很多屬性和方法,用于輔助完成復(fù)雜的數(shù)學(xué)計算任務(wù)。