??引用類(lèi)型的值(對(duì)象)是引用類(lèi)型的一個(gè)實(shí)例华畏。
??在 ECMAscript 中鹏秋,引用類(lèi)型是一種數(shù)據(jù)結(jié)構(gòu),用于將數(shù)據(jù)和功能組織在一起亡笑。
??引用類(lèi)型有時(shí)候也被稱(chēng)為對(duì)象定義侣夷,因?yàn)樗鼈兠枋龅氖且活?lèi)對(duì)象所具有的屬性和方法。
??對(duì)象是某個(gè)特定引用類(lèi)型的實(shí)例仑乌。新對(duì)象是使用 new 操作符后跟一個(gè)構(gòu)造函數(shù)來(lái)創(chuàng)建百拓,構(gòu)造函數(shù)本身就是一個(gè)函數(shù),只不過(guò)該函數(shù)是出于創(chuàng)建新對(duì)象的目的而定義的晰甚。
let person = new Object();
??這行代碼創(chuàng)建了 Object 引用類(lèi)型的一個(gè)新實(shí)例衙传,然后把該實(shí)例保存在了變量 person 中。使用的構(gòu)造函數(shù)是 Object厕九,它只為新對(duì)象定義了默認(rèn)的屬性和方法蓖捶。
1、Object 類(lèi)型
??到目前為止止剖,我們看到的大多數(shù)引用類(lèi)型值都是 Object 類(lèi)型的實(shí)例腺阳。而且落君,Object 也是 ECMAscript 中使用最多的一個(gè)類(lèi)型。
??創(chuàng)建 Object 實(shí)例的方式有兩種亭引。
??第一種是使用 new 操作符后跟 Object 構(gòu)造函數(shù):
let person = new Object();
person.name = 'Jack';
person.age = 21;
??另一種是使用對(duì)象字面量表示法绎速。對(duì)象字面量是對(duì)象定義的一種簡(jiǎn)寫(xiě)形式,目的在于簡(jiǎn)化創(chuàng)建包含大量屬性的對(duì)象的過(guò)程焙蚓。示例:
let person = {
name: 'Jack',
age: 21
};
??對(duì)象字面量也是向函數(shù)傳遞大量可選參數(shù)的首選方式纹冤,例如:
function displayInfo(args) {
let output = '';
if (typeof args.name === 'string') {
output += `Name: ${args.name}\n`;
}
if (typeof args.age === 'number') {
output += `Age: ${args.age}\n`;
}
console.log(output);
}
displayInfo({
name: 'Jack',
age: 21
});
displayInfo({
name: 'Jack'
});
??這種傳遞參數(shù)的模式最適合需要向函數(shù)傳入可選參數(shù)的情形。一般來(lái)講购公,命名參數(shù)雖然容易處理萌京,但在有多個(gè)可選參數(shù)的情況下就會(huì)顯示不夠靈活。最好的做法是對(duì)那些必需值使用命名參數(shù)宏浩,而使用對(duì)象字面量來(lái)封裝多個(gè)可選參數(shù)知残。
??一般來(lái)說(shuō),訪(fǎng)問(wèn)對(duì)象屬性時(shí)使用點(diǎn)表示法比庄。但在 JavaScript 中求妹,也可以使用方括號(hào)表示法來(lái)訪(fǎng)問(wèn)對(duì)象的屬性。使用方括號(hào)表示法時(shí)佳窑,將要訪(fǎng)問(wèn)的屬性以字符串的形式放在方括號(hào)中制恍。示例:
console.log(person['name']); // 'Jack'
console.log(person.name); // 'Jack'
??方括號(hào)語(yǔ)法的主要有點(diǎn)是可以通過(guò)變量來(lái)訪(fǎng)問(wèn)屬性,例如:
let propertyName = 'name';
console.log(person[porpertyName]); // 'Jack'
??如果屬性名中包含會(huì)導(dǎo)致語(yǔ)法錯(cuò)誤的字符神凑,或者屬性名使用的是關(guān)鍵字或保留字净神,也可以使用方括號(hào)表示法。
建議:除非必須使用變量來(lái)訪(fǎng)問(wèn)屬性溉委,否則我們建議使用點(diǎn)表示法鹃唯。
2、Array 類(lèi)型
??除 Object 之外薛躬, Array 類(lèi)型恐怕是 ECMAscript 中最常用的類(lèi)型了俯渤。
ECMAscript 中的數(shù)組與其他語(yǔ)言的不同:
- ECMAscript 數(shù)組的每一項(xiàng)可以保存任何類(lèi)型的數(shù)據(jù)
- ECMAscript 數(shù)組的大小是可以動(dòng)態(tài)調(diào)整的,即可以隨著數(shù)據(jù)的添加自動(dòng)增長(zhǎng)以容納新增數(shù)據(jù)型宝。
創(chuàng)建數(shù)組的基本方式有兩種八匠。第一種使用 Array 構(gòu)造函數(shù),示例:
let colors = new Array();
??如果預(yù)先知道數(shù)組要保存的項(xiàng)目數(shù)量趴酣,也可以給構(gòu)造函數(shù)傳遞該數(shù)量梨树,而該數(shù)量會(huì)自動(dòng)變成 length 屬性的值。例如:
// 創(chuàng)建 length 值為 20 的數(shù)組
let colors = new Array(20);
??也可以向 Array 構(gòu)造函數(shù)傳遞數(shù)組中應(yīng)該包含的項(xiàng)岖寞。例如:
// 創(chuàng)建包含 3 個(gè)字符串值的數(shù)組
let colors = new Array('red', 'blue', 'green');
??給構(gòu)造函數(shù)傳遞一個(gè)值時(shí)抡四,如果傳遞的是數(shù)值,則會(huì)按照該數(shù)值創(chuàng)建包含給定項(xiàng)數(shù)的數(shù)組;如果傳遞的是其他類(lèi)型的參數(shù)指巡,則會(huì)創(chuàng)建包含那個(gè)值的只有一項(xiàng)的數(shù)組淑履。
??使用 Array 構(gòu)造函數(shù)時(shí)可以省略 new 操作符。
??創(chuàng)建數(shù)組的第二種基本方法是使用數(shù)組字面量表示法藻雪。數(shù)組字面量由一對(duì)包含數(shù)組項(xiàng)的方括號(hào)表示秘噪,多個(gè)數(shù)組項(xiàng)之間以逗號(hào)隔開(kāi),示例:
// 創(chuàng)建一個(gè)包含 3 個(gè)字符串的數(shù)組
let colors = ['red', 'blue', 'green'];
// 創(chuàng)建一個(gè)空數(shù)組
let name = [];
// 不要這樣勉耀!會(huì)創(chuàng)建一個(gè)包含 2 或 3(IE8 及之前版本)項(xiàng)的數(shù)組
let values = [1, 2, ];
// 不要這樣指煎!會(huì)創(chuàng)建一個(gè)包含 5 或 6(IE8 及之前版本)項(xiàng)的數(shù)組
let options = [ , , , , , ];
??如上述最后一行代碼所示,在像這種省略值的情況下便斥,每一項(xiàng)都將獲得 undefined 值至壤;這個(gè)結(jié)果與調(diào)用 Array 構(gòu)造函數(shù)時(shí)傳遞項(xiàng)數(shù)在邏輯上是相同的。但是由于 IE(IE8 及之前版本)的實(shí)現(xiàn)與其它瀏覽器不一致枢纠,因此我們不建議使用這種語(yǔ)法像街。
??在讀取和設(shè)置數(shù)組的值是,要使用方括號(hào)并提供相應(yīng)的基于 0 的數(shù)字索引京郑。示例:
let colors = ['red', 'blue', 'green']; // 定義一個(gè)字符串?dāng)?shù)組
console.log(colors[0]); // 顯示第一項(xiàng)
colors[2] = 'black'; // 修改第三項(xiàng)
colors[3] = 'brown'; // 新增第四項(xiàng)
方括號(hào)中的索引表示要訪(fǎng)問(wèn)的值宅广。
數(shù)組的項(xiàng)數(shù)保存在其 length 屬性中葫掉。
??數(shù)組的 length 屬性不是只讀的些举,通過(guò)設(shè)置這個(gè)屬性,可以從數(shù)組的末尾移除項(xiàng)或向數(shù)組中添加新項(xiàng)俭厚。示例:
let colors = ['red', 'blue', 'green']; // 創(chuàng)建一個(gè)包含 3 個(gè)字符串的數(shù)組
colors.length = 2;
console.log(colors[2]); // undefined
??如果將其 length 屬性設(shè)置為大于數(shù)組項(xiàng)數(shù)的值户魏,則新增的每一項(xiàng)都會(huì)取得 undefined 值,示例:
let colors = ['red', 'blue', 'green']; // 創(chuàng)建一個(gè)包含 3 個(gè)字符串的數(shù)組
colors.length = 4;
console.log(colors[3]); // undefined
??利用 length 屬性也可以方便地在數(shù)組末尾添加新項(xiàng)挪挤, 示例:
let colors = ['red', 'blue', 'green']; // 創(chuàng)建一個(gè)包含 3 個(gè)字符串的數(shù)組
colors[colors.length] = 'black'; // (在位置 3)添加一種顏色
colors[colors.length] = 'brown'; // (在位置 4)添加一種顏色
??數(shù)組最多可以包含 4 294 967 295 個(gè)項(xiàng)叼丑。如果想添加的項(xiàng)數(shù)超過(guò)這個(gè)上限,就會(huì)發(fā)生異常扛门。而創(chuàng)建一個(gè)初始大小與這個(gè)上限值接近的數(shù)組鸠信,咋可能會(huì)導(dǎo)致運(yùn)行時(shí)間超長(zhǎng)的腳本錯(cuò)誤。
2.1论寨、檢測(cè)數(shù)組
使用 Array.isArray() 方法檢測(cè)某個(gè)值是不是數(shù)組星立,示例:
if (Array.isArray(value)) {
// 對(duì)數(shù)組執(zhí)行某些操作
}
??支持 Array.isArray() 方法的瀏覽器有 IE9+、Firefox 4+葬凳、Safari 5+绰垂、Opera 10.5+ 和 chrome。
2.2火焰、轉(zhuǎn)換方法
??調(diào)用數(shù)組的 toString() 方法會(huì)返回由數(shù)組中的每個(gè)值的字符串形式拼接而成的一個(gè)以逗號(hào)分隔的字符串劲装,而調(diào)用 valueOf() 方法返回的還是數(shù)組。示例:
let colors = ['red', 'blue', 'green']; // 創(chuàng)建一個(gè)包含 3 個(gè)字符串的數(shù)組
console.log(colors.toString()); // red,blue,green
console.log(colors.valueOf()); // ['red', 'blue', 'green']
console.log(colors); // ['red', 'blue', 'green']
??數(shù)組繼承的 toLocaleString()、toString() 方法占业,在默認(rèn)情況下都會(huì)以逗號(hào)分隔的字符串形式返回?cái)?shù)組項(xiàng)绒怨。
??使用 join() 方法,可以使用不同的分隔符來(lái)構(gòu)建這個(gè)字符串谦疾。join() 方法只接收一個(gè)參數(shù)窖逗,即用作分隔符的字符串,然后返回包含所有數(shù)組項(xiàng)的字符串餐蔬。示例:
let colors = ['red', 'blue', 'green'];
console.log(colors.join(',')); // red,blue,green
console.log(colors.join('||')); // red||blue||green
??如果不給 join() 方法傳入任何值碎紊,或者傳入 undefined,則默認(rèn)使用逗號(hào)作為分隔符樊诺。IE7及更早版本會(huì)錯(cuò)誤的使用字符串 'undefined' 作為分隔符仗考。
??如果數(shù)組中的某一項(xiàng)值是 null 或 undefined,那么該值在 join()词爬、toLocaleString()秃嗜、toString() 方法返回的結(jié)果中以空字符串表示。
2.3顿膨、棧方法
??棧是一種 LIFO(Last-In-First-Out锅锨,后進(jìn)先出)的數(shù)據(jù)結(jié)構(gòu)。棧中項(xiàng)的插入(叫做推入)和移除(叫做彈出)恋沃,只發(fā)生在一個(gè)位置——棧的頂部必搞。
??ECMAscript 為數(shù)組專(zhuān)門(mén)提供了 push() 和 pop() 方法,以便實(shí)現(xiàn)類(lèi)似棧的行為囊咏。
??push() 方法可以接收任意數(shù)量的參數(shù)恕洲,把它們逐個(gè)添加到數(shù)組末尾,并返回修改后數(shù)組的長(zhǎng)度梅割。而 pop() 方法則從數(shù)組末尾移除最后一項(xiàng)霜第,減少數(shù)組的 length 值,然后返回移除的項(xiàng)户辞。示例:
let colors = new Array(); // 創(chuàng)建一個(gè)數(shù)組
let count = colors.push('red', 'green'); // 推入兩項(xiàng)
console.log(count); //2
count = colors.push('black'); // 推入另一項(xiàng)
console.log(count); //3
let item = colors.pop(); // 取得最后一項(xiàng)
console.log(item); // 'black'
console.log(colors.length); //2
2.4泌类、隊(duì)列方法
??隊(duì)列數(shù)據(jù)結(jié)構(gòu)的訪(fǎng)問(wèn)規(guī)則是FIFO(First-In-First-Out,先進(jìn)先出)底燎。隊(duì)列在列表末端添加項(xiàng)刃榨,從列表的前端移除項(xiàng)。
??shift() 方法能夠移除數(shù)組中的第一個(gè)項(xiàng)并返回該項(xiàng)书蚪,同時(shí)將數(shù)組長(zhǎng)度減 1喇澡。結(jié)合使用 shift() 和 push() 方法,可以像使用隊(duì)列一樣使用數(shù)組殊校。示例:
let colors = new Array(); // 創(chuàng)建一個(gè)數(shù)組
let count = colors.push('red', 'green'); // 推入兩項(xiàng)
console.log(count); // 2
count = colors.push('black'); // 推入另一項(xiàng)
console.log(count); // 3
let item = colors.shift(); // 取得第一項(xiàng)
console.log(item); // 'red'
console.log(colors.length); // 2
??unshift() 方法與 shift() 方法用途相反晴玖,它能在數(shù)組前端添加任意個(gè)項(xiàng)并返回新數(shù)組的長(zhǎng)度。同時(shí)使用 unshift() 和 pop() 方法,可以從相反的方向來(lái)模擬隊(duì)列呕屎,即在數(shù)組的前端添加項(xiàng)让簿,從數(shù)組末端移除項(xiàng)。示例:
let colors = new Array(); // 創(chuàng)建一個(gè)數(shù)組
let count = colors.unshift('red', 'green'); // 推入兩項(xiàng)
console.log(count); // 2
count = colors.unshift('black'); // 推入另一項(xiàng)
console.log(count); // 3
let item = colors.pop(); // 取得最后一項(xiàng)
console.log(item); // 'green'
console.log(colors.length); // 2
2.5秀睛、重排序方法
??數(shù)組中存在兩個(gè)可以直接用來(lái)重排序的方法: reverse() 和 sort() 方法尔当。
??reverse() 方法會(huì)反轉(zhuǎn)數(shù)組項(xiàng)的順序。示例:
let values = [1, 2, 3, 4, 5];
values.reverse();
console.log(values); // [5, 4, 3, 2, 1];
??默認(rèn)情況下蹂安,sort() 方法按升序排列數(shù)組項(xiàng)——即最小的值位于最前面椭迎,最大值排在最后面。為了實(shí)現(xiàn)排序田盈,sort() 方法會(huì)調(diào)用每個(gè)數(shù)組項(xiàng)的 toString() 轉(zhuǎn)型方法畜号,然后比較得到的字符串,以確定如何排序允瞧。即使數(shù)組中的每一項(xiàng)都是數(shù)值备韧,sort() 方法比較的也是字符串州叠,示例:
let values = [0, 1, 5, 10, 15];
values.sort();
console.log(values); // [0, 1, 10, 15, 5];
??sort() 方法可以(僅可以)接收一個(gè)比較函數(shù)作為參數(shù),以便我們制定數(shù)組的排序午笛。接收函數(shù)的返回值判斷數(shù)組的排序拒课。
a 和 b 比較之后:
- 返回一個(gè)小于 0 的值酌儒, a 在 b 之前轧叽。
- 返回 0罗洗,a、b 的順序不變廊驼。
- 返回一個(gè)大于 0 的值据过,a 在 b 之后。
??對(duì)于數(shù)值類(lèi)型或者其 valueOf() 方法會(huì)返回?cái)?shù)值類(lèi)型的對(duì)象類(lèi)型妒挎,可以使用下面的比較函數(shù),示例:
function compare(a, b) {
return a - b;
}
let values = [0, 1, 5, 10, 15];
values.sort(compare);
console.log(values); // [0, 1, 10, 15, 5];
??對(duì)于其它對(duì)象類(lèi)型西饵,可以使用下列比較函數(shù)酝掩,指定返回值:
function compare(value1, value2) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
reverse() 和 sort() 方法的返回值是經(jīng)過(guò)排序之后的數(shù)組。
2.6眷柔、操作方法
??concat() —— 可以基于當(dāng)前數(shù)組中的所有項(xiàng)創(chuàng)建一個(gè)新數(shù)組期虾。
??具體來(lái)說(shuō),這個(gè)方法會(huì)先創(chuàng)建當(dāng)前數(shù)組的一個(gè)副本然后將接收到的參數(shù)添加到這個(gè)副本的末尾驯嘱,最后返回新構(gòu)建的數(shù)組镶苞。在沒(méi)有給 concat() 方法傳遞參數(shù)的情況下,它只是復(fù)制當(dāng)前數(shù)組并返回副本鞠评。如果傳遞給 concat() 方法的是一或多個(gè)數(shù)組茂蚓,則該方法會(huì)將這些數(shù)組中的每一項(xiàng)都添加到結(jié)果數(shù)組中。如果傳遞的值不是數(shù)組,這些值就會(huì)被簡(jiǎn)單地添加到結(jié)果數(shù)組的末尾聋涨。
let colors = ['red', 'green', 'blue'];
let colors2 = colors.concat('yellow', ['black', 'brown']);
console.log(colors); // ['red', 'green', 'blue']
console.log(colors2); // ['red', 'green', 'blue', 'yellow', 'black', 'brown']
??slice() —— 它能夠基于當(dāng)前數(shù)組中的一或多個(gè)項(xiàng)創(chuàng)建一個(gè)新數(shù)組晾浴。
??slice() 方法可以接受一或兩個(gè)參數(shù),即要返回項(xiàng)的起始和結(jié)束位置牍白。在只有一個(gè)參數(shù)的情況下脊凰,slice() 方法返回從該參數(shù)指定位置開(kāi)始到當(dāng)前數(shù)組末尾的所有項(xiàng)。如果有兩個(gè)參數(shù)茂腥,該方法返回起始和結(jié)束位置之間的項(xiàng)——但不包括結(jié)束位置的項(xiàng)狸涌。示例:
let colors = ['red', 'green', 'blue', 'yellow', 'black', 'brown'];
let colors2 = colors.slice(1);
let colors3 = colors.slice(1,4);
console.log(colors2); // ['green', 'blue', 'yellow', 'black', 'brown']
console.log(colors3); // ['green', 'blue', 'yellow']
slice() 方法不會(huì)影響原始數(shù)組。
??如果 slice()方法的參數(shù)中有一個(gè)負(fù)數(shù)最岗,則用數(shù)組長(zhǎng)度加上該數(shù)來(lái)確定相應(yīng)的位置杈抢。例如,在一個(gè)包含 5 項(xiàng)的數(shù)組上調(diào)用 slice(-2, -1)與調(diào)用 slice(3, 4) 得到的結(jié)果相同仑性。如果結(jié)束位置小于起始位置惶楼,則返回空數(shù)組。
splice() —— 最強(qiáng)大的數(shù)組方法诊杆。
刪除
功能:可以刪除任意數(shù)量的項(xiàng)歼捐。
參數(shù):2 個(gè);要?jiǎng)h除的第一項(xiàng)的位置晨汹,要?jiǎng)h除的項(xiàng)數(shù)
示例:
let colors = ['red', 'green', 'blue', 'yellow'];
let colors2 = colors.splice(1, 2); // 從位置 1 開(kāi)始刪除 2 項(xiàng)
console.log(colors); // ['red', 'yellow']
console.log(colors2); // ['green', 'blue']豹储, 返回的數(shù)組中包含 2 項(xiàng)
插入
功能:可以向指定位置插入任意數(shù)量的項(xiàng)。
參數(shù):3淘这;起始位置剥扣,0(要?jiǎng)h除的項(xiàng)數(shù)),要插入的項(xiàng)(如果要插入多個(gè)項(xiàng)铝穷,可以再傳入第四钠怯、第五,以至任意項(xiàng)曙聂。
示例:
let colors = ['red', 'green', 'blue', 'yellow'];
let colors2 = colors.splice(1, 0, 'black', 'orange'); // 從位置 1 開(kāi)始插入 2 項(xiàng)
console.log(colors); // ['red', 'black', 'orange', 'green', 'blue', 'yellow']
console.log(colors2); // []晦炊, 返回一個(gè)空數(shù)組
替換
功能:可以向指定位置插入任意數(shù)量的項(xiàng),且同時(shí)刪除任意數(shù)量的項(xiàng)宁脊。
參數(shù):3断国;起始位置,要?jiǎng)h除的項(xiàng)數(shù)榆苞,要插入的任意數(shù)量的項(xiàng)
示例:
let colors = ['red', 'green', 'blue', 'yellow'];
let colors2 = colors.splice(1, 1, 'pink', 'purple'); // 從位置 1 開(kāi)始刪除 1 項(xiàng)稳衬,插入 2 項(xiàng)
console.log(colors); // ['red', 'pink', 'purple', 'blue', 'yellow']
console.log(colors2); // ['green'], 返回的數(shù)組中包含 1 項(xiàng)
??splice() 方法始終會(huì)返回一個(gè)數(shù)組坐漏,該數(shù)組中包含從原始數(shù)組中刪除的項(xiàng)(如果沒(méi)有刪除任何項(xiàng)薄疚,則返回一個(gè)空數(shù)組)碧信。
2.7、位置方法
indexOf()
功能:返回要查找的項(xiàng)在數(shù)組中的位置输涕,從數(shù)組開(kāi)頭向后查找音婶。
參數(shù):2;要查找的項(xiàng)莱坎,(可選)查找起點(diǎn)位置的索引衣式。
lastIndexOf()
功能:返回要查找的項(xiàng)在數(shù)組中的位置,從數(shù)組末尾向前查找檐什。
參數(shù):2碴卧;要查找的項(xiàng),(可選)查找起點(diǎn)位置的索引乃正。
??這兩個(gè)方法都返回要查找的項(xiàng)在數(shù)組中的位置住册,或者在沒(méi)有找到的情況下返回 -1。使用全等操作符(===)進(jìn)行比較瓮具。
示例:
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
console.log(numbers.indexOf(4)); // 3荧飞,從頭開(kāi)始向后的第一個(gè) 4
console.log(numbers.lastIndexOf(4)); // 5,從末尾開(kāi)始向前的第一個(gè) 4
console.log(numbers.indexOf(4, 4)); // 5名党,從第 4 位開(kāi)始向后的第一個(gè) 4
console.log(numbers.lastIndexOf(4, 4)); // 3叹阔,從第 4 位開(kāi)始向前的第一個(gè) 4
let person = { name: "Nicholas" };
let people = [{ name: "Nicholas" }];
let morePeople = [person];
console.log(people.indexOf(person)); // -1
console.log(morePeople.indexOf(person)); // 0
2.8、迭代方法
??數(shù)組的每個(gè)迭代方法都接收 2 參數(shù):要在每一項(xiàng)上運(yùn)行的函數(shù)和(可選的)運(yùn)行該函數(shù)的作用域?qū)ο蟆绊?this 的值传睹。
??傳入這些這些方法中的函數(shù)會(huì)接受 3 個(gè)參數(shù):數(shù)組項(xiàng)的值耳幢、該項(xiàng)在數(shù)組中的位置、數(shù)組對(duì)象本身欧啤。
以下是 5 個(gè)迭代方法的作用:
- every():對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù)睛藻,如果該函數(shù)對(duì)每一項(xiàng)都返回 true ,則返回 true邢隧。
- some():對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù)店印,如果該函數(shù)對(duì)任一項(xiàng)返回 true,則返回 true府框。
- filter():對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù)吱窝,返回該函數(shù)會(huì)返回 true 的項(xiàng)組成的數(shù)組。
- map():對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù)迫靖,返回每次函數(shù)調(diào)用的結(jié)果組成的數(shù)組。
- forEach():對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù)兴使,這個(gè)方法沒(méi)有返回值系宜。
??以上方法都不會(huì)修改數(shù)組中包含的值。
??every() 和 some() 都用于查詢(xún)數(shù)組中的項(xiàng)是否滿(mǎn)足某個(gè)條件发魄。示例:
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let everyResult = numbers.every(function(item, index, array){
return (item > 2);
});
console.log(everyResult); // false
let someResult = numbers.some(function(item, index, array){
return (item > 2);
});
console.log(someResult); // true
??filter() 函數(shù):利用指定的函數(shù)確定是否在返回的數(shù)組中包含某一項(xiàng)盹牧。
// 要返回一個(gè)所有數(shù)值都大于 2 的數(shù)組
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let filterResult = numbers.filter(function(item, index, array){
return (item > 2);
});
console.log(filterResult); // [3, 4, 5, 4, 3]
??map() 函數(shù):返回一個(gè)數(shù)組俩垃,而這個(gè)數(shù)組的每一項(xiàng)都是在原始數(shù)組中的對(duì)應(yīng)項(xiàng)運(yùn)行傳入函數(shù)的結(jié)果。cif
// 給數(shù)組中的每一項(xiàng)乘以 2
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let mapResult = numbers.map(function(item, index, array){
return item * 2;
});
console.log(mapResult); // [2, 4, 6, 8, 10, 8, 6, 4, 2]
??forEach() 方法:對(duì)數(shù)組的每一項(xiàng)運(yùn)行傳入的函數(shù)汰寓,沒(méi)有返回值口柳。本質(zhì)上與使用 for 循環(huán)迭代數(shù)組一樣。
let numbers = [1,2,3,4,5,4,3,2,1];
numbers.forEach(function(item, index, array){
// 執(zhí)行某些操作
});
2.9有滑、歸并方法
??reduce() 和 reduceRight() 是歸并數(shù)組的方法跃闹。兩個(gè)方法都會(huì)迭代數(shù)組的所有項(xiàng),然后構(gòu)建一個(gè)最終返回的值毛好。
??reduce() 方法從數(shù)組的第一項(xiàng)開(kāi)始望艺,逐個(gè)遍歷到最后。
??reduceRight() 方法從數(shù)組的最后一項(xiàng)開(kāi)始肌访,向前遍歷到第一項(xiàng)找默。
??這兩個(gè)方法都接收兩個(gè)參數(shù):在每一項(xiàng)上調(diào)用的函數(shù),(可選)最為歸并基礎(chǔ)的初始值吼驶。
??傳給 reduce() 和 reduceRight() 的函數(shù)接收 4 個(gè)函數(shù):前一個(gè)值惩激、當(dāng)前值、項(xiàng)的索引蟹演、數(shù)組對(duì)象风钻。這個(gè)函數(shù)的返回的任何值都會(huì)作為第一個(gè)參數(shù)自動(dòng)傳給下一項(xiàng)。
??第一次迭代發(fā)生在數(shù)組的第二項(xiàng)上轨帜,因此第一個(gè)參數(shù)是數(shù)組的第一項(xiàng)魄咕,第二個(gè)參數(shù)是數(shù)組的第二項(xiàng)。
// 求數(shù)組中所有值之和
let values = [1, 2, 3, 4, 5];
let sum = values.reduce(function(prev, cur, index, array){
return prev + cur;
});
console.log(sum); // 15
??第一次執(zhí)行回調(diào)函數(shù)蚌父, prev 是 1(數(shù)組的第一項(xiàng))哮兰, cur 是 2(數(shù)組的第二項(xiàng));第二次苟弛,prev 是 3(1 + 2 的結(jié)果)喝滞,cur 是 3(數(shù)組的第三項(xiàng))。這個(gè)過(guò)程會(huì)持續(xù)到吧數(shù)組中的每一項(xiàng)都訪(fǎng)問(wèn)一遍膏秫,最后返回結(jié)果右遭。
??reduceRight() 的作用類(lèi)似,只不過(guò)方向相反缤削。
// 求數(shù)組中所有值之和
let values = [1, 2, 3, 4, 5];
let sum = values.reduceRight(function(prev, cur, index, array){
return prev + cur;
});
console.log(sum); // 15
??上述例子中窘哈,第一次執(zhí)行回調(diào)函數(shù), prev 是 5(數(shù)組的最后一項(xiàng))亭敢, cur 是 4(數(shù)組的倒數(shù)第二項(xiàng))滚婉;
3、Date 類(lèi)型
??Date 類(lèi)型使用自 UTC(Coordinated Universal Time帅刀, 國(guó)際協(xié)調(diào)時(shí)間)1970 年 1 月 1 日午夜(零時(shí))開(kāi)始經(jīng)過(guò)的毫秒數(shù)來(lái)保存日期让腹。在使用這種數(shù)據(jù)存儲(chǔ)格式的條件下远剩,Date 類(lèi)型保存的日期能夠精確到 1970 年 1 月 1 日之前或之后的 285 616 年。
??創(chuàng)建一個(gè)日期對(duì)象骇窍,使用 new 操作符和 Date 構(gòu)造函數(shù)瓜晤,示例:
let now = new Date();
??調(diào)用 Date 構(gòu)造函數(shù)而不傳遞參數(shù)的情況下,新創(chuàng)建的對(duì)象自動(dòng)獲得當(dāng)前日期和時(shí)間腹纳。如果想根據(jù)特定的日期和時(shí)間創(chuàng)建日期對(duì)象痢掠,必須傳入表示改日期的毫秒數(shù)(即從 UTC 時(shí)間 1970 年 1 月 1 日午夜起至該日期止經(jīng)過(guò)的毫秒數(shù))。為了簡(jiǎn)化這一計(jì)算過(guò)程只估,使用以下兩個(gè)方法:Date.parse() 和 Date.UTC()志群。
??Date.parse() 方法接收一個(gè)表示日期的字符串參數(shù),然后嘗試根據(jù)這個(gè)字符串返回相應(yīng)日期的毫秒數(shù)蛔钙。日期格式通常為以下幾種類(lèi)型:
- '月/日/年'锌云,如 12/25/2017;
- '英文月名 日,年',如 December 25,2017;
- '英文星期幾 英文月名 日 年 時(shí):分:秒 時(shí)區(qū)'吁脱,如 Monday December 25 2017 00:00:00 GMT-0700;
- ISO 8601 擴(kuò)展格式 YYYY-MM-DDTHH:mm:ss.sssZ桑涎,如 2017-12-25T00:00:00。
// 2017 年 12 月 25 日創(chuàng)建一個(gè)日期對(duì)象
let someDate = new Date(Date.parse('May 25, 2004'));
// 等價(jià)于
let someDate = new Date('May 25, 2004');
??如果傳入 Date.parse() 方法的字符串不能表示日期兼贡,那么會(huì)返回 NaN攻冷。如上所述,直接將表示日期的字符串傳遞給 Date 構(gòu)造函數(shù)遍希,也會(huì)在后臺(tái)調(diào)用 Date.parse()等曼。
??Date.UTC() 方法同樣也返回表示日期的毫秒數(shù)。
Date.UTC() 的參數(shù)分別是:
- 年份(必需)
- 基于 0 的月份(一月是 0凿蒜,二月是 1禁谦,以此類(lèi)推)(必需)
- 月中的一天(1 到 31)
- 小時(shí)數(shù)(0 到 23)
- 分鐘
- 秒
- 毫秒數(shù)
??如果沒(méi)有提供月中的天數(shù),則假設(shè)天數(shù)為 1废封;如果省略其他參數(shù)州泊,則統(tǒng)統(tǒng)假設(shè)為 0。示例:
// GMT 時(shí)間 2000 年 1 月 1 日午夜零時(shí)
let y2k = new Date(Date.UTC(2000, 0));
// GMT 時(shí)間 2017 年 12 月 25 日下午 5:55:55
let allFives = new Date(Date.UTC(2017, 11, 25, 17, 55, 55));
??Date 構(gòu)造函數(shù)會(huì)模仿 Date.UTC()漂洋,但有一點(diǎn)明顯不同:日期和時(shí)間都基于本地時(shí)區(qū)而非 GMT 來(lái)創(chuàng)建遥皂。不過(guò),Date 構(gòu)造函數(shù)接收的參數(shù)仍然與 Date.UTC() 相同刽漂。因此演训,如果第一個(gè)參數(shù)是數(shù)值, Date() 構(gòu)造函數(shù)就會(huì)假設(shè)該值是日期中的年份贝咙,而第二個(gè)參數(shù)是月份仇祭,以此類(lèi)推,示例:
// 本地時(shí)間 2000 年 1 月 1 日午夜零時(shí)
let y2k = new Date(2000, 0);
// 本地時(shí)間 2017 年 12 月 25 日下午 5:55:55
let allFives = new Date(2017, 11, 25, 17, 55, 55);
??Date.now() 方法:返回調(diào)用這個(gè)方法時(shí)的日期和時(shí)間的毫秒數(shù)颈畸。這個(gè)方法簡(jiǎn)化了使用 Date 對(duì)象分析代碼的工作乌奇。例如:
// 取得開(kāi)始時(shí)間
let start = Date.now();
// 調(diào)用函數(shù)
doSomething();
// 取得停止時(shí)間
let stop = Date.now();
let result = stop – start;
// 等價(jià)于
// 取得開(kāi)始時(shí)間
let start = +new Date();
// 調(diào)用函數(shù)
doSomething();
// 取得停止時(shí)間
let stop = +new Date();
let result = stop - start;
??使用 + 操作符把 Date 對(duì)象轉(zhuǎn)換為字符串。
3.1眯娱、繼承的方法
??與其它引用類(lèi)型一樣礁苗, Date 類(lèi)型也重寫(xiě)了 toLocaleString()、toString()徙缴、valueOf() 方法试伙。
??Date 類(lèi)型的 toLocaleString() 方法會(huì)按照與瀏覽器設(shè)置的地區(qū)相適應(yīng)的格式返回日期和時(shí)間。這大致意味著時(shí)間格式中會(huì)包含 AM 或 PM于样,但不會(huì)包含時(shí)區(qū)信息(當(dāng)然疏叨,具體的格式會(huì)因?yàn)g覽器而異)。
??Date 類(lèi)型的 toString() 方法則通常返回帶有時(shí)區(qū)信息的日期和時(shí)間穿剖,其中時(shí)間一般以軍用時(shí)間(即小時(shí)的范圍是 0 到 23)表示蚤蔓。
??下面給出了在不同瀏覽器中調(diào)用 toLocaleString() 和 toString() 方法,輸出 PST(Pacific Standard Time糊余,太平洋標(biāo)準(zhǔn)時(shí)間)時(shí)間 2007 年 2 月 1 日午夜零時(shí)的結(jié)果秀又。
// Internet Explorer 8
toLocaleString() — Thursday, February 01, 2007 12:00:00 AM
toString() — Thu Feb 1 00:00:00 PST 2007
// Firefox 3.5
toLocaleString() — Thursday, February 01, 2007 12:00:00 AM
toString() — Thu Feb 01 2007 00:00:00 GMT-0800 (Pacific Standard Time)
// Safari 4
toLocaleString() — Thursday, February 01, 2007 00:00:00
toString() — Thu Feb 01 2007 00:00:00 GMT-0800 (Pacific Standard Time)
// Chrome 4
toLocaleString() — Thu Feb 01 2007 00:00:00 GMT-0800 (Pacific Standard Time)
toString() — Thu Feb 01 2007 00:00:00 GMT-0800 (Pacific Standard Time)
// Opera 10
toLocaleString() — 2/1/2007 12:00:00 AM
toString() — Thu, 01 Feb 2007 00:00:00 GMT-0800
??顯然,這兩個(gè)方法在不同的瀏覽器中返回的日期和時(shí)間格式可謂大相徑庭贬芥。事實(shí)上吐辙,toLocaleString() 和 toString() 的這一差別僅在調(diào)試代碼時(shí)比較有用,而在顯示日期和時(shí)間時(shí)沒(méi)有什么價(jià)值蘸劈。
??Date 類(lèi)型的 valueOf() 方法昏苏,不返回字符串,而是返回日期的毫秒表示威沫。因此贤惯,可以方便使用比較操作符(小于或大于)來(lái)比較日期值。示例:
var date1 = new Date(2017, 0, 1); // 'January 1, 2017'
var date2 = new Date(2017, 1, 1); // 'February 1, 2017'
console.log(date1 < date2); // true
console.log(date1 > date2); // false
3.2壹甥、日期格式化方法
Date() 類(lèi)型有一些專(zhuān)門(mén)用于將日期格式化為字符串的方法救巷,
- toDateString() —— 以特定于實(shí)現(xiàn)的格式顯示星期幾、月句柠、日浦译、年;
- toTimeString() —— 以特定于實(shí)現(xiàn)的格式顯示時(shí)溯职、分精盅、秒、時(shí)區(qū)谜酒;
- toLocaleDateString() —— 以特定于地區(qū)的格式顯示星期幾叹俏、月、日僻族、年粘驰;
- toLocaleTimeString() —— 以特定于地區(qū)的格式顯示時(shí)屡谐、分、秒蝌数;
- toUTCString() —— 以特定于實(shí)現(xiàn)的格式完整的 UTC 日期愕掏。
??與 toLocaleString() 和 toString() 方法一樣段磨,以上這些字符串格式方法的輸出也是因?yàn)g覽器而異的绍傲,因此沒(méi)有哪一個(gè)方法能夠用來(lái)在用戶(hù)界面中顯示一致的日期信息。
3.3呜达、日期/時(shí)間組件方法
??以下是直接取得和設(shè)置日期值中特定部分的方法:
本地日期:
方法 | 說(shuō)明 |
---|---|
getTime() | 返回毫秒數(shù)唆貌;與 valueOf() 方法返回值相同 |
getFullYear() | 返回4位數(shù)的年份 |
getMonth() | 返回月份滑潘,其中 0 表示一月,11 表示十二月 |
getDate() | 返回月份中的天數(shù)(1 到 31) |
getDay() | 返回星期的星期幾(其中 0 表示星期日锨咙,6 表示星期六) |
getHours() | 返回小時(shí)數(shù)(0 到 23) |
getMinutes() | 返回分鐘數(shù)(0 到 59) |
getSeconds() | 返回秒數(shù)(0 到 59) |
getMilliseconds() | 返回毫秒數(shù) |
getTimezoneOffset() | 返回本地時(shí)間與 UTC 時(shí)間相差的分鐘數(shù) |
UTC 日期:
方法 | 說(shuō)明 |
---|---|
getUTCFullYear() | 返回UTC日期的4位數(shù)年份 |
getUTCMonth() | 返回UTC日期中的月份语卤,其中0表示一月,11表示十二月 |
getUTCDate() | 返回UTC日期月份中的天數(shù)(1到31) |
getUTCDay() | 返回UTC日期中星期的星期幾(其中0表示星期日蓖租,6表示星期六) |
getUTCHours() | 返回UTC日期中的小時(shí)數(shù)(0到23) |
getUTCMinutes() | 返回UTC日期中的分鐘數(shù)(0到59) |
getUTCSeconds() | 返回UTC日期中的秒數(shù)(0到59) |
getUTCMilliseconds() | 返回UTC日期中的毫秒數(shù) |
設(shè)置本地日期:
方法 | 說(shuō)明 |
---|---|
setTime(毫秒) | 以毫秒數(shù)設(shè)置日期粱侣,會(huì)改變整個(gè)日期 |
setFullYear(年) | 設(shè)置日期的年份。傳入的年份值必須是 4 位數(shù)字 |
setMonth(月) | 設(shè)置日期的月份蓖宦。傳入的月份值必須大于 0齐婴,超過(guò) 11 則增加年份 |
setDate(日) | 設(shè)置日期月份中的天數(shù)。如果傳入的值超過(guò)了該月中應(yīng)有的天數(shù)稠茂,則增加月份 |
setHours(時(shí)) | 設(shè)置日期中的小時(shí)數(shù)柠偶。傳入的值超過(guò)了 23 則增加月份中的天數(shù) |
setMinutes(分) | 設(shè)置日期中的分鐘數(shù)。傳入的值超過(guò) 59 則增加小時(shí)數(shù) |
setSeconds(秒) | 設(shè)置日期中的秒數(shù)睬关。傳入的值超過(guò)了 59 會(huì)增加分鐘數(shù) |
setMilliseconds(毫秒) | 設(shè)置日期中的毫秒數(shù) |
設(shè)置 UTC 日期:
方法 | 說(shuō)明 |
---|---|
setUTCFullYear(年) | 設(shè)置UTC日期的年份诱担。傳入的年份值必須是 4 位數(shù)字 |
setUTCMonth(月) | 設(shè)置UTC日期的月份。傳入的月份值必須大于 0电爹,超過(guò)11則增加年份 |
setUTCDate(日) | 設(shè)置UTC日期月份中的天數(shù)蔫仙。如果傳入的值超過(guò)了該月中應(yīng)有的天數(shù),則增加月份 |
setUTCHours(時(shí)) | 設(shè)置UTC日期中的小時(shí)數(shù)丐箩。傳入的值超過(guò)了23則增加月份中的天數(shù) |
setUTCMinutes(分) | 設(shè)置UTC日期中的分鐘數(shù)摇邦。傳入的值超過(guò)59則增加小時(shí)數(shù) |
setUTCSeconds(秒) | 設(shè)置UTC日期中的秒數(shù)。傳入的值超過(guò)了59會(huì)增加分鐘數(shù) |
setUTCMilliseconds(毫秒) | 設(shè)置UTC日期中的毫秒數(shù) |
4屎勘、RegExp 類(lèi)型
??ECMAScript 通過(guò) RegExp 類(lèi)型來(lái)支持正則表達(dá)式施籍。2 種創(chuàng)建正則表達(dá)式的方法:
- 使用字面量形式來(lái)定義正則表達(dá)式
- 使用 RegExp 構(gòu)造函數(shù)
使用字面量形式來(lái)定義正則表達(dá)式
let expression = / pattern / flags ;
??其中的模式(pattern)部分可以是任何簡(jiǎn)單或復(fù)雜的正則表達(dá)式,可以包含字符類(lèi)概漱、限定符丑慎、分組、向前查找、反向引用竿裂。每個(gè)正則表達(dá)式都可帶有一或多個(gè)標(biāo)志(flags)玉吁,用以標(biāo)明正則表達(dá)式的行為。
正則表達(dá)式的匹配模式支持下列 3 個(gè)標(biāo)志:
- g:表示全局(global)模式铛绰,即模式將被應(yīng)用于所有字符串诈茧,而非在發(fā)現(xiàn)第一個(gè)匹配項(xiàng)時(shí)立即停止;
- i:表示不區(qū)分大小寫(xiě)(case-insensitive)模式捂掰,即在確定匹配項(xiàng)時(shí)忽略模式與字符串的大小寫(xiě);
- m:表示多行(multiline)模式曾沈,即在到達(dá)一行文本末尾時(shí)還會(huì)繼續(xù)查找下一行中是否存在與模式匹配的項(xiàng)这嚣。
??因此,一個(gè)正則表達(dá)式就是一個(gè)模式與上述 3 個(gè)標(biāo)志的組合體塞俱。示例:
// 匹配字符串中所有 "at" 的實(shí)例
let pattern1 = /at/g;
// 匹配第一個(gè) "bat" 或 "cat"姐帚,不區(qū)分大小寫(xiě)
let pattern2 = /[bc]at/i;
// 匹配所有以 "at" 結(jié)尾的 3 個(gè)字符的組合,不區(qū)分大小寫(xiě)
let pattern3 = /.at/gi;
??與其他語(yǔ)言中的正則表達(dá)式類(lèi)似障涯,模式中使用的所有元字符都必須轉(zhuǎn)義罐旗。正則表達(dá)式中的元字符包括:
( [ { \ ^ $ | ) ? * + . ] }
??這些元字符在正則表達(dá)式中都有一或多種特殊用途,因此如果想要匹配字符串中包含的這些字符唯蝶,就必須對(duì)它們進(jìn)行轉(zhuǎn)義九秀。示例:
// 匹配第一個(gè) "bat" 或 "cat",不區(qū)分大小寫(xiě)
let pattern1 = /[bc]at/i;
// 匹配第一個(gè) "[bc]at" 粘我,不區(qū)分大小寫(xiě)
let patter2 = /\[bc\]at/i;
??上述例子中鼓蜒,pattern1 匹配第一個(gè) "bat" 或 "cat",不區(qū)分大小寫(xiě)征字。而要想直接匹配 "[bc]at" 的話(huà)都弹,就需要像定義 pattern2 一樣,對(duì)其中的兩個(gè)方括號(hào)進(jìn)行轉(zhuǎn)義匙姜。
// 匹配所有以 "at" 結(jié)尾的 3 個(gè)字符的組合畅厢,不區(qū)分大小寫(xiě)
let pattern3 = /.at/gi;
// 匹配所有".at",不區(qū)分大小寫(xiě)
let pattern4 = /\.at/gi;
??上述例子中氮昧,對(duì)于 pattern3 來(lái)說(shuō)框杜,句點(diǎn)表示位于"at"之前的任意一個(gè)可以構(gòu)成匹配項(xiàng)的字符。但如果想匹配".at"郭计,則必須對(duì)句點(diǎn)本身進(jìn)行轉(zhuǎn)義霸琴,如 pattern4 所示。
使用 RegExp 構(gòu)造函數(shù)來(lái)創(chuàng)建正則表達(dá)式
RegExp 構(gòu)造函數(shù)接收 2 個(gè)參數(shù):要匹配的字符串模式昭伸、可選的標(biāo)志字符串梧乘。
可以使用字面量定義的任何表達(dá)式,都可以使用構(gòu)造函數(shù)來(lái)定義。示例:
// 匹配第一個(gè) "bat" 或 "cat"选调,不區(qū)分大小寫(xiě)
let pattern1 = /[bc]at/i;
// 與 pattern1 相同夹供,只不過(guò)是使用構(gòu)造函數(shù)創(chuàng)建的
let pattern2 = new RegExp("[bc]at", "i");
??要注意的是,傳遞給 RegExp 構(gòu)造函數(shù)的兩個(gè)參數(shù)都是字符串(不能把正則表達(dá)式字面量傳遞給 RegExp 構(gòu)造函數(shù))仁堪。
??由于 RegExp 構(gòu)造函數(shù)的模式參數(shù)是字符串哮洽,所以在某些情況下要對(duì)字符進(jìn)行雙重轉(zhuǎn)義。所有元字符都必須雙重轉(zhuǎn)義弦聂,那些已經(jīng)轉(zhuǎn)義過(guò)的字符也是如此鸟辅。例如:字符\在字符串中通常被轉(zhuǎn)義為\,而在正則表達(dá)式字符串中就會(huì)變成\\莺葫。
字面量模式 | 等價(jià)的字符串 |
---|---|
/\[bc\]at/ | "\\[bc\\]at" |
/\.at/ | "\\.at" |
/name\/age/ | "name\\/age" |
/\d.\d{1,2}/ | "\\d.\\d{1,2}" |
/\w\\hello\\123/ | "\w\\\\hello\\\\123" |
4.1匪凉、RegExp 實(shí)例屬性
??RegExp 的每個(gè)實(shí)例都具有下列屬性,通過(guò)這些屬性可以取得有關(guān)模式的各種信息捺檬。
- global:布爾值再层,表示是否設(shè)置了 g 標(biāo)志。
- ignoreCase:布爾值堡纬,表示是否設(shè)置了 i 標(biāo)志聂受。
- lastIndex:整數(shù),表示開(kāi)始搜索下一個(gè)匹配項(xiàng)的字符位置烤镐,從 0 算起蛋济。
- multiline:布爾值,表示是否設(shè)置了 m 標(biāo)志职车。
- source:正則表達(dá)式的字符串表示瘫俊,按照字面量形式而非傳入構(gòu)造函數(shù)中的字符串模式返回。
??通過(guò)這些屬性可以獲知一個(gè)正則表達(dá)式的各方面信息悴灵,但卻沒(méi)有多大用處扛芽,因?yàn)檫@些信息全都包含在模式聲明中。例如:
let pattern1 = /\[bc\]at/i;
console.log(pattern1.global); // false
console.log(pattern1.ignoreCase); // true
console.log(pattern1.multiline); // false
console.log(pattern1.lastIndex); // 0
console.log(pattern1.source); // "\[bc\]at"
let pattern2 = new RegExp("\\[bc\\]at", "i");
console.log(pattern2.global); // false
console.log(pattern2.ignoreCase); // true
console.log(pattern2.multiline); // false
console.log(pattern2.lastIndex); // 0
console.log(pattern2.source); // "\[bc\]at"
4.1积瞒、RegExp 實(shí)例方法
RegExp 對(duì)象的方法:
- exec()川尖,該方法是專(zhuān)門(mén)為捕獲組而設(shè)計(jì)的;
- test(),判斷目標(biāo)字符串與某個(gè)模式是否匹配茫孔;
- toLocaleString()叮喳,返回正則表達(dá)式的字面量;
- toString()缰贝,返回正則表達(dá)式的字面量馍悟;
- valueOf(),返回正則表達(dá)式本身剩晴。
exec()方法
??exec() 接受一個(gè)參數(shù)锣咒,即要應(yīng)用模式的字符串侵状,然后返回包含第一個(gè)匹配項(xiàng)信息的數(shù)組;或者在沒(méi)有匹配項(xiàng)的情況下返回 null毅整。
??exec() 返回的數(shù)組雖然是 Array 的實(shí)例趣兄,但包含兩個(gè)額外的屬性:index 和 input。其中悼嫉,index 表示匹配項(xiàng)在字符串中的位置艇潭,而 input 表示應(yīng)用正則表達(dá)式的字符串。
??在數(shù)組中戏蔑,第一項(xiàng)是與整個(gè)模式匹配的字符串蹋凝,其他項(xiàng)是與模式中的捕獲組匹配的字符串(如果模式中沒(méi)有捕獲組,則該數(shù)組只包含一項(xiàng))辛臊。示例:
let text = "mom and dad and baby";
let pattern = /mom( and dad( and baby)?)?/gi;
let matches = pattern.exec(text);
console.log(matches.index); // 0
console.log(matches.input); // "mom and dad and baby"
console.log(matches[0]); // "mom and dad and baby"
console.log(matches[1]); // " and dad and baby"
console.log(matches[2]); // " and baby"
??對(duì)于 exec() 方法而言仙粱,即使在模式中設(shè)置了全局標(biāo)志(g),它每次也只會(huì)返回一個(gè)匹配項(xiàng)彻舰。在不設(shè)置全局標(biāo)志的情況下,在同一個(gè)字符串上多次調(diào)用 exec() 將始終返回第一個(gè)匹配項(xiàng)的信息候味。而在設(shè)
置全局標(biāo)志的情況下刃唤,每次調(diào)用 exec() 則都會(huì)在字符串中繼續(xù)查找新匹配項(xiàng),示例:
let text = "cat, bat, sat, fat";
let pattern1 = /.at/;
let matches = pattern1.exec(text);
console.log(matches.index); // 0
console.log(matches[0]); // cat
console.log(pattern1.lastIndex); // 0
matches = pattern1.exec(text);
console.log(matches.index); // 0
console.log(matches[0]); // cat
console.log(pattern1.lastIndex); // 0
let pattern2 = /.at/g;
let matches = pattern2.exec(text);
console.log(matches.index); // 0
console.log(matches[0]); // cat
console.log(pattern2.lastIndex); // 3
matches = pattern2.exec(text);
console.log(matches.index); // 5
console.log(matches[0]); // bat
console.log(pattern2.lastIndex); // 8
test()方法
??test() 接受一個(gè)字符串參數(shù)白群。在模式與該參數(shù)匹配的情況下返回 true尚胞;否則,返回 false帜慢。
??在只想知道目標(biāo)字符串與某個(gè)模式是否匹配笼裳,但不需要知道其文本內(nèi)容的情況下,使用這個(gè)方法非常方便粱玲。因此躬柬,test()方法經(jīng)常被用在 if 語(yǔ)句中,示例:
let text = "000-00-0000";
let pattern = /\d{3}-\d{2}-\d{4}/;
if (pattern.test(text)){
console.log("The pattern was matched.");
}
??在上述例子中抽减,我們使用正則表達(dá)式來(lái)測(cè)試了一個(gè)數(shù)字序列允青。如果輸入的文本與模式匹配,則顯示一條消息卵沉。這種用法經(jīng)常出現(xiàn)在驗(yàn)證用戶(hù)輸入的情況下颠锉,因?yàn)槲覀冎幌胫垒斎胧遣皇怯行В劣谒鼮槭裁礋o(wú)效就無(wú)關(guān)緊要了史汗。
toLocaleString() 和 toString() 方法
??RegExp 實(shí)例繼承的 toLocaleString()和 toString()方法都會(huì)返回正則表達(dá)式的字面量琼掠,與創(chuàng)建正則表達(dá)式的方式無(wú)關(guān)。例如:
let pattern = new RegExp("\\[bc\\]at", "gi");
console.log(pattern.toString()); // /\[bc\]at/gi
console.log(pattern.toLocaleString()); // /\[bc\]at/gi
valueOf() 方法
正則表達(dá)式的 valueOf()方法返回正則表達(dá)式本身停撞。示例:
let pattern = /\[bc\]at/gi;
console.log(pattern.toString()); // /\[bc\]at/gi
console.log(typeof pattern.toString()); // string
console.log(pattern.valueOf()); // /\[bc\]at/gi
console.log(typeof pattern.valueOf()); // object
4.3瓷蛙、RegExp 構(gòu)造函數(shù)屬性
??RegExp 構(gòu)造函數(shù)包含一些屬性。這些屬性適用于作用域中的所有正則表達(dá)式,并且基于所執(zhí)行的最近一次正則表達(dá)式操作而變化速挑。關(guān)于這些屬性的另一個(gè)獨(dú)特之處谤牡,就是可以通過(guò)兩種方式訪(fǎng)問(wèn)它們。換句話(huà)說(shuō)姥宝,這些屬性分別有一個(gè)長(zhǎng)屬性名和一個(gè)短屬性名翅萤。
RegExp 構(gòu)造函數(shù)的屬性:
長(zhǎng)屬性名 | 短屬性名 | 說(shuō)明 |
---|---|---|
input | $_ | 最近一次要匹配的字符串 |
lastMatch | $& | 最近一次的匹配項(xiàng) |
lastParen | $+ | 最近一次匹配的捕獲組 |
leftContext | $` | input字符串中l(wèi)astMatch之前的文本 |
multiline | $* | 布爾值,表示是否所有表達(dá)式都使用多行模式 |
rightContext | $' | Input字符串中l(wèi)astMatch之后的文本 |
示例:
let text = "this has been a short summer";
let pattern = /(.)hort/g;
if (pattern.test(text)){
console.log(RegExp.input); // this has been a short summer
console.log(RegExp.leftContext); // this has been a
console.log(RegExp.rightContext); // summer
console.log(RegExp.lastMatch); // short
console.log(RegExp.lastParen); // s
console.log(RegExp.multiline); // false
}
??以上代碼創(chuàng)建了一個(gè)模式腊满,匹配任何一個(gè)字符后跟 hort套么,而且把第一個(gè)字符放在了一個(gè)捕獲組中。
RegExp 構(gòu)造函數(shù)的各個(gè)屬性返回了下列值:
- input 屬性返回了原始字符串碳蛋;
- leftContext 屬性返回了單詞 short 之前的字符串胚泌;
- rightContext 屬性返回了 short 之后的字符串;
- lastMatch 屬性返回最近一次與整個(gè)正則表達(dá)式匹配的字符串肃弟,即short玷室;
- lastParen 屬性返回最近一次匹配的捕獲組,即例子中的 s笤受。
??例子使用的長(zhǎng)屬性名都可以用相應(yīng)的短屬性名來(lái)代替穷缤。只不過(guò),由于這些短屬性名大都不是有效的 ECMAScript 標(biāo)識(shí)符箩兽,因此必須通過(guò)方括號(hào)語(yǔ)法來(lái)訪(fǎng)問(wèn)它們津肛,示例:
let text = "this has been a short summer";
let pattern = /(.)hort/g;
if (pattern.test(text)){
console.log(RegExp.$_); // this has been a short summer
console.log(RegExp["$`"]); // this has been a
console.log(RegExp["$'"]); // summer
console.log(RegExp["$&"]); // short
console.log(RegExp["$+"]); // s
console.log(RegExp["$*"]); // false
}
??除了上面介紹的幾個(gè)屬性之外,還有多達(dá) 9 個(gè)用于存儲(chǔ)捕獲組的構(gòu)造函數(shù)屬性汗贫。訪(fǎng)問(wèn)這些屬性的語(yǔ)法是 RegExp.$1身坐、RegExp.$2…RegExp.$9,分別用于存儲(chǔ)第一落包、第二……第九個(gè)匹配的捕獲組部蛇。在調(diào)用 exec() 或 test() 方法時(shí),這些屬性會(huì)被自動(dòng)填充妥色。示例:
let text = "this has been a short summer";
let pattern = /(..)or(.)/g;
if (pattern.test(text)){
console.log(RegExp.$1); // sh
console.log(RegExp.$2); // t
}
??這里創(chuàng)建了一個(gè)包含兩個(gè)捕獲組的模式搪花,并用該模式測(cè)試了一個(gè)字符串。即使 test() 方法只返回一個(gè)布爾值嘹害,但 RegExp 構(gòu)造函數(shù)的屬性 $1 和 $2 也會(huì)被匹配相應(yīng)捕獲組的字符串自動(dòng)填充撮竿。
4.4、模式的局限性
ECMAScript 正則表達(dá)式不支持的特性:
- 匹配字符串開(kāi)始和結(jié)尾的\A 和\Z 錨(但支持以插入符號(hào)(^)和美元符號(hào)($)來(lái)匹配字符串的開(kāi)始和結(jié)尾)
- 向后查找(lookbehind)(但完全支持向前查找(lookahead))
- 并集和交集類(lèi)
- 原子組(atomic grouping)
- Unicode 支持(單個(gè)字符除外笔呀,如\uFFFF)
- 命名的捕獲組(但支持編號(hào)的捕獲組)
- s(single幢踏,單行)和 x(free-spacing,無(wú)間隔)匹配模式
- 條件匹配
- 正則表達(dá)式注釋
5许师、Function 類(lèi)型
??每個(gè)函數(shù)都是 Function 類(lèi)型的實(shí)例房蝉,而且都與其他引用類(lèi)型一樣具有屬性和方法僚匆。由于函數(shù)是對(duì)象,因此函數(shù)名實(shí)際上也是一個(gè)指向函數(shù)對(duì)象的指針搭幻,不會(huì)與某個(gè)函數(shù)綁定咧擂。
定義函數(shù):
- 使用函數(shù)聲明語(yǔ)法定義;
- 定義變量并將其初始化為一個(gè)函數(shù)檀蹋;
- 使用 Function 構(gòu)造函數(shù)松申。
function sum (num1, num2) {
return num1 + num2;
}
let sum = function(num1, num2){
return num1 + num2;
};
let sum = new Function("num1", "num2", "return num1 + num2"); // 不推薦
??上述第二個(gè)例子,定義了變量 sum 并將其初始化為一個(gè)函數(shù)俯逾。function 關(guān)鍵字后面沒(méi)有函數(shù)名贸桶,這是因?yàn)樵谑褂煤瘮?shù)表達(dá)式定義函數(shù)時(shí),沒(méi)有必要使用函數(shù)名——通過(guò)變量 sum 即可以引用函數(shù)桌肴。另外皇筛,還要注意函數(shù)末尾有一個(gè)分號(hào),就像聲明其他變量時(shí)一樣坠七。
??上述第三個(gè)例子水醋,從技術(shù)角度講,這是一個(gè)函數(shù)表達(dá)式彪置。但是离例,我們不推薦讀者使用這種方法定義函數(shù),因?yàn)檫@種語(yǔ)法會(huì)導(dǎo)致解析兩次代碼(第一次是解析常規(guī) ECMAScript 代碼悉稠,第二次是解析傳入構(gòu)造函數(shù)中的字符串),從而影響性能艘包。不過(guò)的猛,這種語(yǔ)法對(duì)于理解“函數(shù)是對(duì)象,函數(shù)名是指針”的概念倒是非常直觀(guān)的想虎。
??由于函數(shù)名僅僅是指向函數(shù)的指針卦尊,因此函數(shù)名與包含對(duì)象指針的其他變量沒(méi)有什么不同。換句話(huà)說(shuō)舌厨,一個(gè)函數(shù)可能會(huì)有多個(gè)名字岂却,示例:
function sum(num1, num2){
return num1 + num2;
}
console.log(sum(10,10)); // 20
let anotherSum = sum;
console.log(anotherSum(10, 10)); // 20
sum = null;
console.log(anotherSum(10, 10)); // 20
??以上代碼首先定義了一個(gè)名為 sum()的函數(shù),用于求兩個(gè)值的和裙椭。然后躏哩,又聲明了變量 anotherSum,并將其設(shè)置為與 sum 相等(將 sum 的值賦給 anotherSum)揉燃。此時(shí)扫尺,anotherSum 和 sum 就都指向了同一個(gè)函數(shù),因此 anotherSum()也可以被調(diào)用并返回結(jié)果炊汤。即使將 sum 設(shè)置為 null正驻,讓它與函數(shù)“斷絕關(guān)系”弊攘,但仍然可以正常調(diào)用anotherSum()。
注意姑曙,使用不帶圓括號(hào)的函數(shù)名是訪(fǎng)問(wèn)函數(shù)指針襟交,而非調(diào)用函數(shù)。
5.1伤靠、沒(méi)有重載(深入理解)
??將函數(shù)名想象為指針捣域,也有助于理解為什么 ECMAScript 中沒(méi)有函數(shù)重載的概念。
function addSomeNumber(num){
return num + 100;
}
function addSomeNumber(num) {
return num + 200;
}
let result = addSomeNumber(100); // 300
// 等價(jià)于
let addSomeNumber = function (num){
return num + 100;
};
addSomeNumber = function (num) {
return num + 200;
};
let result = addSomeNumber(100); // 300
??聲明了兩個(gè)同名函數(shù)醋界,而結(jié)果則是后面的函數(shù)覆蓋了前面的函數(shù)竟宋。通過(guò)觀(guān)察重寫(xiě)之后的代碼,很容易看清楚到底是怎么回事兒——在創(chuàng)建第二個(gè)函數(shù)時(shí)形纺,實(shí)際上覆蓋了引用第一個(gè)函數(shù)的變量 addSomeNumber丘侠。
5.2、函數(shù)聲明與函數(shù)表達(dá)式
??解析器在向執(zhí)行環(huán)境中加載數(shù)據(jù)時(shí)逐样,對(duì)函數(shù)聲明和函數(shù)表達(dá)式并非一視同仁蜗字。解析器會(huì)率先讀取函數(shù)聲明,并使其在執(zhí)行任何代碼之前可用(可以訪(fǎng)問(wèn))脂新;至于函數(shù)表達(dá)式挪捕,則必須等到解析器執(zhí)行到它所在的代碼行智厌,才會(huì)真正被解釋執(zhí)行套鹅。示例:
console.log(sum(10,10));
function sum(num1, num2){
return num1 + num2;
}
??以上代碼可以正常運(yùn)行仓犬。因?yàn)樵诖a開(kāi)始執(zhí)行之前偶摔,解析器就已經(jīng)通過(guò)一個(gè)名為函數(shù)聲明提升(function declaration hoisting)的過(guò)程卒密,讀取并將函數(shù)聲明添加到執(zhí)行環(huán)境中旨椒。對(duì)代碼求值時(shí)腌乡,JavaScript 引擎在第一遍會(huì)聲明函數(shù)并將它們放到源代碼樹(shù)的頂部盛龄。所以斩启,即使聲明函數(shù)的代碼在調(diào)用它的代碼后面序调,JavaScript 引擎也能把函數(shù)聲明提升到頂部。
console.log(sum(10,10));
let sum = function(num1, num2){
return num1 + num2;
};
??以上代碼會(huì)在運(yùn)行期間產(chǎn)生錯(cuò)誤兔簇,原因在于函數(shù)位于一個(gè)初始化語(yǔ)句中发绢,而不是一個(gè)函數(shù)聲明。換句話(huà)說(shuō)垄琐,在執(zhí)行到函數(shù)所在的語(yǔ)句之前边酒,變量 sum 中不會(huì)保存有對(duì)函數(shù)的引用;而且此虑,由于第一行代碼就會(huì)導(dǎo)致 “unexpected identifier”(意外標(biāo)識(shí)符)錯(cuò)誤甚纲,實(shí)際上也不會(huì)執(zhí)行到下一行。
??除了什么時(shí)候可以通過(guò)變量訪(fǎng)問(wèn)函數(shù)這一點(diǎn)區(qū)別之外朦前,函數(shù)聲明與函數(shù)表達(dá)式的語(yǔ)法其實(shí)是等價(jià)的介杆。
5.3鹃操、作為值的函數(shù)
??因?yàn)?ECMAScript 中的函數(shù)名本身就是變量,所以函數(shù)也可以作為值來(lái)使用春哨。也就是說(shuō)荆隘,不僅可以像傳遞參數(shù)一樣把一個(gè)函數(shù)傳遞給另一個(gè)函數(shù),而且可以將一個(gè)函數(shù)作為另一個(gè)函數(shù)的結(jié)果返回赴背。
將函數(shù)作為參數(shù)傳遞給另一個(gè)函數(shù)
function callSomeFunction(someFunction, someArgument){
return someFunction(someArgument);
}
??這個(gè)函數(shù)接受兩個(gè)參數(shù)椰拒。第一個(gè)參數(shù)應(yīng)該是一個(gè)函數(shù),第二個(gè)參數(shù)應(yīng)該是要傳遞給該函數(shù)的一個(gè)值凰荚。
示例:
function add10(num){
return num + 10;
}
let result1 = callSomeFunction(add10, 10);
console.log(result1); // 20
function getGreeting(name){
return "Hello, " + name;
}
let result2 = callSomeFunction(getGreeting, "Nicholas");
console.log(result2); // "Hello, Nicholas"
??這里的 callSomeFunction() 函數(shù)是通用的燃观,即無(wú)論第一個(gè)參數(shù)中傳遞進(jìn)來(lái)的是什么函數(shù),它都會(huì)返回執(zhí)行第一個(gè)參數(shù)后的結(jié)果便瑟。
??要訪(fǎng)問(wèn)函數(shù)的指針而不執(zhí)行函數(shù)的話(huà)缆毁,必須去掉函數(shù)名后面的那對(duì)圓括號(hào)。因此上面例子中傳遞給 callSomeFunction() 的是 add10 和 getGreeting到涂,而不是執(zhí)行它們之后的結(jié)果脊框。
將函數(shù)作為另一個(gè)函數(shù)的結(jié)果返回
??可以從一個(gè)函數(shù)中返回另一個(gè)函數(shù),而且這也是極為有用的一種技術(shù)践啄。例如浇雹,假設(shè)有一個(gè)對(duì)象數(shù)組,我們想要根據(jù)某個(gè)對(duì)象屬性對(duì)數(shù)組進(jìn)行排序屿讽。而傳遞給數(shù)組 sort() 方法的比較函數(shù)要接收兩個(gè)參數(shù)昭灵,即要比較的值》ヌ福可是虎锚,我們需要一種方式來(lái)指明按照哪個(gè)屬性來(lái)排序。要解決這個(gè)問(wèn)題衩婚,可以定義一個(gè)函數(shù),它接收一個(gè)屬性名效斑,然后根據(jù)這個(gè)屬性名來(lái)創(chuàng)建一個(gè)比較函數(shù)非春。示例:
function createComparisonFunction(propertyName) {
return function(object1, object2){
let value1 = object1[propertyName];
let value2 = object2[propertyName];
if (value1 < value2){
return -1;
} else if (value1 > value2){
return 1;
} else {
return 0;
}
};
}
// 具體使用實(shí)例:
let data = [{name: "Zachary", age: 28}, {name: "Nicholas", age: 29}];
data.sort(createComparisonFunction("name"));
console.log(data[0].name); // Nicholas
data.sort(createComparisonFunction("age"));
console.log(data[0].name); // Zachary
5.4、函數(shù)內(nèi)部屬性
在函數(shù)內(nèi)部缓屠,有兩個(gè)特殊的對(duì)象:
- arguments
- this
??arguments 是一個(gè)類(lèi)數(shù)組對(duì)象奇昙,包含著傳入函數(shù)中的所有參數(shù)。雖然 arguments 的主要用途是保存函數(shù)參數(shù)敌完,但這個(gè)對(duì)象還有一個(gè)名叫 callee 的屬性储耐,該屬性是一個(gè)指針,指向擁有這個(gè) arguments 對(duì)象的函數(shù)滨溉。示例:
// 階乘函數(shù)
function factorial(num){
if (num <=1) {
return 1;
} else {
return num * factorial(num-1)
}
}
??定義階乘函數(shù)一般都要用到遞歸算法什湘;如上面的代碼所示长赞,在函數(shù)有名字,而且名字以后也不會(huì)變的情況下闽撤,這樣定義沒(méi)有問(wèn)題得哆。但問(wèn)題是這個(gè)函數(shù)的執(zhí)行與函數(shù)名 factorial 緊緊耦合在了一起。為了消除這種緊密耦合的現(xiàn)象哟旗,可以像下面這樣使用 arguments.callee贩据。
function factorial(num){
if (num <=1) {
return 1;
} else {
return num * arguments.callee(num-1)
}
}
??在這個(gè)重寫(xiě)后的 factorial()函數(shù)的函數(shù)體內(nèi),沒(méi)有再引用函數(shù)名 factorial闸餐。這樣饱亮,無(wú)論引用函數(shù)時(shí)使用的是什么名字,都可以保證正常完成遞歸調(diào)用舍沙。示例:
let trueFactorial = factorial;
factorial = function(){
return 0;
};
console.log(trueFactorial(5)); // 120
console.log(factorial(5)); // 0
??在此近上,變量 trueFactorial 獲得了 factorial 的值,實(shí)際上是在另一個(gè)位置上保存了一個(gè)函數(shù)的指針场勤。然后戈锻,我們又將一個(gè)簡(jiǎn)單地返回 0 的函數(shù)賦值給 factorial 變量。如果像原來(lái)的 factorial() 那樣不使用 arguments.callee和媳,調(diào)用 trueFactorial() 就會(huì)返回 0格遭。可是留瞳,在解除了函數(shù)體內(nèi)的代碼與函數(shù)名的耦合狀態(tài)之后拒迅,trueFactorial() 仍然能夠正常地計(jì)算階乘;至于 factorial()她倘,它現(xiàn)在只是一個(gè)返回 0 的函數(shù)璧微。
注意:嚴(yán)格模式下,訪(fǎng)問(wèn) arguments.callee 會(huì)導(dǎo)致錯(cuò)誤硬梁。
??this 引用的是函數(shù)據(jù)以執(zhí)行的環(huán)境對(duì)象——或者也可以說(shuō)是 this 值(當(dāng)在網(wǎng)頁(yè)的全局作用域中調(diào)用函數(shù)時(shí)前硫,this 對(duì)象引用的就是 window)。示例:
window.color = "red";
let o = { color: "blue" };
function sayColor(){
console.log(this.color);
}
sayColor(); // "red"
o.sayColor = sayColor;
o.sayColor(); // "blue"
??上面這個(gè)函數(shù) sayColor() 是在全局作用域中定義的荧止,它引用了 this 對(duì)象屹电。由于在調(diào)用函數(shù)之前,this 的值并不確定跃巡,因此 this 可能會(huì)在代碼執(zhí)行過(guò)程中引用不同的對(duì)象危号。當(dāng)在全局作用域中調(diào)用 sayColor() 時(shí),this 引用的是全局對(duì)象 window素邪;換句話(huà)說(shuō)外莲,對(duì) this.color 求值會(huì)轉(zhuǎn)換成對(duì) window.color 求值,于是結(jié)果就返回了 "red"兔朦。而當(dāng)把這個(gè)函數(shù)賦給對(duì)象 o 并調(diào)用 o.sayColor() 時(shí)偷线,this 引用的是對(duì)象 o磨确,因此對(duì) this.color 求值會(huì)轉(zhuǎn)換成對(duì) o.color 求值,結(jié)果就返回了 "blue"淋昭。
注意:函數(shù)的名字僅僅是一個(gè)包含指針的變量而已俐填。因此,即使是在不同的環(huán)境中執(zhí)行翔忽,全局的 sayColor() 函數(shù)與 o.sayColor() 指向的仍然是同一個(gè)函數(shù)英融。
??caller 是函數(shù)對(duì)象的屬性,這個(gè)屬性中保存著調(diào)用當(dāng)前函數(shù)的函數(shù)的引用歇式,如果是在全局作用域中調(diào)用當(dāng)前函數(shù)驶悟,它的值為 null。示例:
function outer(){
inner();
}
function inner(){
console.log(inner.caller);
}
outer();
??以上代碼會(huì)打印 outer() 函數(shù)的源代碼材失。因?yàn)?outer()調(diào)用了 inter()痕鳍,所以 inner.caller 就指向 outer()。
??為了實(shí)現(xiàn)更松散的耦合龙巨,也可以通過(guò) arguments.callee.caller 來(lái)訪(fǎng)問(wèn)相同的信息笼呆。示例:
function outer(){
inner();
}
function inner(){
console.log(arguments.callee.caller);
}
outer();
??arguments 也有一個(gè) arguments.caller 屬性,這個(gè)屬性始終返回 undefined旨别。定義這個(gè)屬性是為了分清 arguments.caller 和函數(shù)的 caller 屬性诗赌。以上變化都是為了加強(qiáng)這門(mén)語(yǔ)言的安全性,這樣第三方代碼就不能在相同的環(huán)境里窺視其他代碼了秸弛。
5.5铭若、函數(shù)屬性和方法
??ECMAScript 中的函數(shù)是對(duì)象,因此函數(shù)也有屬性和方法递览。每個(gè)函數(shù)都包含兩個(gè)屬性:length 和 prototype叼屠。
??length 屬性表示函數(shù)希望接收的命名參數(shù)的個(gè)數(shù)。示例:
function sayName(name){
console.log(name);
}
function sum(num1, num2){
return num1 + num2;
}
function sayHi(){
console.log("hi");
}
console.log(sayName.length); // 1
console.log(sum.length); // 2
console.log(sayHi.length); // 0
??對(duì)于 ECMAScript 中的引用類(lèi)型而言绞铃,prototype 是保存它們所有實(shí)例方法的真正所在镜雨。換句話(huà)說(shuō),諸如 toString() 和 valueOf() 等方法實(shí)際上都保存在 prototype 名下儿捧,只不過(guò)是通過(guò)各自對(duì)象的實(shí)例訪(fǎng)問(wèn)罷了冷离。
??每個(gè)函數(shù)都包含兩個(gè)非繼承而來(lái)的方法:apply() 和 call()。這兩個(gè)方法的用途都是在特定的作用域中調(diào)用函數(shù)纯命,實(shí)際上等于設(shè)置函數(shù)體內(nèi) this 對(duì)象的值。
??apply() 方法接收兩個(gè)參數(shù):一個(gè)是在其中運(yùn)行函數(shù)的作用域痹栖,另一個(gè)是參數(shù)數(shù)組亿汞。其中,第二個(gè)參數(shù)可以是 Array 的實(shí)例揪阿,也可以是 arguments 對(duì)象疗我。示例:
function sum(num1, num2){
return num1 + num2;
}
function callSum1(num1, num2){
return sum.apply(this, arguments); // 傳入 arguments 對(duì)象
}
function callSum2(num1, num2){
return sum.apply(this, [num1, num2]); // 傳入數(shù)組
}
console.log(callSum1(10, 10)); //20
console.log(callSum2(10, 10)); //20
??在上面這個(gè)例子中咆畏,callSum1() 在執(zhí)行 sum()函數(shù)時(shí)傳入了 this 作為 this 值(因?yàn)槭窃谌肿饔糜蛑姓{(diào)用的,所以傳入的就是 window 對(duì)象)和 arguments 對(duì)象吴裤。而 callSum2 同樣也調(diào)用了 sum() 函數(shù)旧找,但它傳入的則是 this 和一個(gè)參數(shù)數(shù)組。這兩個(gè)函數(shù)都會(huì)正常執(zhí)行并返回正確的結(jié)果麦牺。
??call() 方法與 apply() 方法的作用相同钮蛛,它們的區(qū)別僅在于接收參數(shù)的方式不同。對(duì)于 call() 方法而言剖膳,第一個(gè)參數(shù)是 this 值沒(méi)有變化魏颓,變化的是其余參數(shù)都直接傳遞給函數(shù)。換句話(huà)說(shuō)吱晒,在使用 call() 方法時(shí)甸饱,傳遞給函數(shù)的參數(shù)必須逐個(gè)列舉出來(lái),示例:
function sum(num1, num2){
return num1 + num2;
}
function callSum(num1, num2){
return sum.call(this, num1, num2);
}
console.log(callSum(10, 10)); // 20
??在使用 call() 方法的情況下仑濒,callSum() 必須明確地傳入每一個(gè)參數(shù)叹话。結(jié)果與使用 apply() 沒(méi)有什么不同。
??至于是使用 apply() 還是 call()墩瞳,完全取決于你采取哪種給函數(shù)傳遞參數(shù)的方式最方便驼壶。如果你打算直接傳入 arguments 對(duì)象,或者包含函數(shù)中先接收到的也是一個(gè)數(shù)組矗烛,那么使用 apply() 肯定更方便辅柴;否則,選擇 call() 可能更合適瞭吃。(在不給函數(shù)傳遞參數(shù)的情況下碌嘀,使用哪個(gè)方法都無(wú)所謂。)
??事實(shí)上歪架,傳遞參數(shù)并非 apply() 和 call() 真正的用武之地股冗;它們真正強(qiáng)大的地方是能夠擴(kuò)充函數(shù)賴(lài)以運(yùn)行的作用域。示例:
window.color = "red";
let o = { color: "blue" };
function sayColor(){
console.log(this.color);
}
sayColor(); // red
sayColor.call(this); // red
sayColor.call(window); // red
sayColor.call(o); // blue
??sayColor() 是作為全局函數(shù)定義的和蚪,當(dāng)在全局作用域中調(diào)用它時(shí)止状,它確實(shí)會(huì)顯示 "red"——因?yàn)閷?duì) this.color 的求值會(huì)轉(zhuǎn)換成對(duì) window.color 的求值。
??而 sayColor.call(this) 和 sayColor.call(window)攒霹,則是兩種顯式地在全局作用域中調(diào)用函數(shù)的方式怯疤,結(jié)果當(dāng)然都會(huì)顯示 "red"。但是催束,當(dāng)運(yùn)行 sayColor.call(o) 時(shí)集峦,函數(shù)的執(zhí)行環(huán)境就不一樣了,因?yàn)榇藭r(shí)函數(shù)體內(nèi)的 this 對(duì)象指向了 o,于是結(jié)果顯示的是 "blue"塔淤。
??使用 call() 或 apply() 來(lái)擴(kuò)充作用域的最大好處摘昌,就是對(duì)象不需要與方法有任何耦合關(guān)系。在前面例子的第一個(gè)版本中高蜂,我們是先將 sayColor() 函數(shù)放到了對(duì)象 o 中聪黎,然后再通過(guò) o 來(lái)調(diào)用它的;而在這里重寫(xiě)的例子中备恤,就不需要先前那個(gè)多余的步驟了稿饰。
??bind() 方法會(huì)創(chuàng)建一個(gè)函數(shù)的實(shí)例,其 this 值會(huì)被綁定到傳給 bind() 函數(shù)的值烘跺。示例:
window.color = "red";
let o = { color: "blue" };
function sayColor(){
console.log(this.color);
}
let objectSayColor = sayColor.bind(o);
objectSayColor(); // blue
??在這里湘纵,sayColor() 調(diào)用 bind() 并傳入對(duì)象 o,創(chuàng)建了 objectSayColor() 函數(shù)滤淳。objectSayColor() 函數(shù)的 this 值等于 o梧喷,因此即使是在全局作用域中調(diào)用這個(gè)函數(shù),也會(huì)看到 "blue"脖咐。
??每個(gè)函數(shù)繼承的 toLocaleString() 和 toString() 方法始終都返回函數(shù)的代碼铺敌。返回代碼的格式則因?yàn)g覽器而異 —— 有的返回的代碼與源代碼中的函數(shù)代碼一樣,而有的則返回函數(shù)代碼的內(nèi)部表示屁擅,即由解析器刪除了注釋并對(duì)某些代碼作了改動(dòng)后的代碼偿凭。由于存在這些差異,我們無(wú)法根據(jù)這兩個(gè)方法返回的結(jié)果來(lái)實(shí)現(xiàn)任何重要功能派歌;不過(guò)弯囊,這些信息在調(diào)試代碼時(shí)倒是很有用。另外一個(gè)繼承的 valueOf() 方法同樣也只返回函數(shù)代碼胶果。
6匾嘱、基本包裝類(lèi)型
??為了便于操作基本類(lèi)型值,ECMAScript 還提供了 3 個(gè)特殊的引用類(lèi)型:Boolean早抠、Number 和 String霎烙。這些類(lèi)型與本章介紹的其他引用類(lèi)型相似,但同時(shí)也具有與各自的基本類(lèi)型相應(yīng)的特殊行為蕊连。實(shí)際上悬垃,每當(dāng)讀取一個(gè)基本類(lèi)型值的時(shí)候,后臺(tái)就會(huì)創(chuàng)建一個(gè)對(duì)應(yīng)的基本包裝類(lèi)型的對(duì)象甘苍,從而讓我們能夠調(diào)用一些方法來(lái)操作這些數(shù)據(jù)尝蠕。示例:
let s1 = "some text";
let s2 = s1.substring(2);
??這個(gè)例子中的變量 s1 包含一個(gè)字符串,字符串當(dāng)然是基本類(lèi)型值载庭。而下一行調(diào)用了 s1 的 substring()方法看彼,并將返回的結(jié)果保存在了 s2 中扇谣。我們知道,基本類(lèi)型值不是對(duì)象闲昭,因而從邏輯上講它們不應(yīng)該有方法。
??其實(shí)靡挥,為了讓我們實(shí)現(xiàn)這種直觀(guān)的操作序矩,后臺(tái)已經(jīng)自動(dòng)完成了一系列的處理。當(dāng)?shù)诙写a訪(fǎng)問(wèn) s1 時(shí)跋破,訪(fǎng)問(wèn)過(guò)程處于一種讀取模式簸淀,也就是要從內(nèi)存中讀取這個(gè)字符串的值。而在讀取模式中訪(fǎng)問(wèn)字符串時(shí)毒返,后臺(tái)都會(huì)自動(dòng)完成下列處理:
- 創(chuàng)建 String 類(lèi)型的一個(gè)實(shí)例租幕;
- 在實(shí)例上調(diào)用指定的方法;
- 銷(xiāo)毀這個(gè)實(shí)例拧簸。
??可以將以上三個(gè)步驟想象成是執(zhí)行了下列 ECMAScript 代碼劲绪。
let s1 = new String("some text");
let s2 = s1.substring(2);
s1 = null;
??經(jīng)過(guò)此番處理,基本的字符串值就變得跟對(duì)象一樣了盆赤。而且贾富,上面這三個(gè)步驟也分別適用于 Boolean 和 Number 類(lèi)型對(duì)應(yīng)的布爾值和數(shù)字值。
??引用類(lèi)型與基本包裝類(lèi)型的主要區(qū)別就是對(duì)象的生存期牺六。使用 new 操作符創(chuàng)建的引用類(lèi)型的實(shí)例颤枪,在執(zhí)行流離開(kāi)當(dāng)前作用域之前都一直保存在內(nèi)存中。而自動(dòng)創(chuàng)建的基本包裝類(lèi)型的對(duì)象淑际,則只存在于一行代碼的執(zhí)行瞬間畏纲,然后立即被銷(xiāo)毀。這意味著我們不能在運(yùn)行時(shí)為基本類(lèi)型值添加屬性和方法春缕。示例:
let s1 = "some text";
s1.color = "red";
console.log(s1.color); // undefined
??在此盗胀,第二行代碼試圖為字符串 s1 添加一個(gè) color 屬性。但是淡溯,當(dāng)?shù)谌写a再次訪(fǎng)問(wèn) s1 時(shí)读整,其 color 屬性不見(jiàn)了。問(wèn)題的原因就是第二行創(chuàng)建的 String 對(duì)象在執(zhí)行第三行代碼時(shí)已經(jīng)被銷(xiāo)毀了咱娶。第三行代碼又創(chuàng)建自己的 String 對(duì)象米间,而該對(duì)象沒(méi)有 color 屬性。
??當(dāng)然膘侮,可以顯式地調(diào)用 Boolean屈糊、Number 和 String 來(lái)創(chuàng)建基本包裝類(lèi)型的對(duì)象。不過(guò)琼了,應(yīng)該在絕對(duì)必要的情況下再這樣做逻锐,因?yàn)檫@種做法很容易讓人分不清自己是在處理基本類(lèi)型還是引用類(lèi)型的值夫晌。
??對(duì)基本包裝類(lèi)型的實(shí)例調(diào)用 typeof 會(huì)返回 "object",而且所有基本包裝類(lèi)型的對(duì)象都會(huì)被轉(zhuǎn)換為布爾值 true昧诱。
??Object 構(gòu)造函數(shù)也會(huì)像工廠(chǎng)方法一樣晓淀,根據(jù)傳入值的類(lèi)型返回相應(yīng)基本包裝類(lèi)型的實(shí)例。示例:
let obj = new Object("some text");
console.log(obj instanceof String); // true
??把字符串傳給 Object 構(gòu)造函數(shù)盏档,就會(huì)創(chuàng)建 String 的實(shí)例凶掰;而傳入數(shù)值參數(shù)會(huì)得到 Number 的實(shí)]例,傳入布爾值參數(shù)就會(huì)得到 Boolean 的實(shí)例蜈亩。
??要注意的是懦窘,使用 new 調(diào)用基本包裝類(lèi)型的構(gòu)造函數(shù),與直接調(diào)用同名的轉(zhuǎn)型函數(shù)是不一樣的稚配。示例:
let value = "25";
let number = Number(value); // 轉(zhuǎn)型函數(shù)
console.log(typeof number); // "number"
let obj = new Number(value); // 構(gòu)造函數(shù)
console.log(typeof obj); // "object"
??在這個(gè)例子中畅涂,變量 number 中保存的是基本類(lèi)型的值 25树酪,而變量 obj 中保存的是 Number 的實(shí)例闪水。
??盡管我們不建議顯式地創(chuàng)建基本包裝類(lèi)型的對(duì)象,但它們操作基本類(lèi)型值的能力還是相當(dāng)重要的眷篇。而每個(gè)基本包裝類(lèi)型都提供了操作相應(yīng)值的便捷方法愤惰。
6.1苇经、Boolean 類(lèi)型
??Boolean 類(lèi)型是與布爾值對(duì)應(yīng)的引用類(lèi)型。要?jiǎng)?chuàng)建 Boolean 對(duì)象宦言,可以像下面這樣調(diào)用 Boolean 構(gòu)造函數(shù)并傳入 true 或 false 值扇单。示例:
let booleanObject = new Boolean(true);
Boolean 類(lèi)型的實(shí)例
- 重寫(xiě)了 valueOf() 方法,返回基本類(lèi)型值 true 或 false奠旺;
- 重寫(xiě)了 toString() 方法蜘澜,返回字符串 "true" 和 "false";
- 重寫(xiě)了 toLocaleString() 方法响疚,返回字符串 "true" 和 "false"鄙信。
let BooleanFalse= new Boolean(true);
console.log(BooleanFalse.valueOf()); // false
console.log(typeof BooleanFalse.valueOf()); // boolean
console.log(BooleanFalse.toString()); // false
console.log(typeof BooleanFalse.toString()); // string
console.log(BooleanFalse.toLocaleString()); // false
console.log(typeof BooleanFalse.toLocaleString()); // string
??Boolean 對(duì)象在 ECMAScript 中的用處不大,因?yàn)樗?jīng)常會(huì)造成人們的誤解忿晕。其中最常見(jiàn)的問(wèn)題就是在布爾表達(dá)式中使用 Boolean 對(duì)象装诡,例如:
let falseObject = new Boolean(false);
let result = falseObject && true;
console.log(result); // true
let falseValue = false;
result = falseValue && true;
console.log(result); // false
??在這個(gè)例子中,我們使用 false 值創(chuàng)建了一個(gè) Boolean 對(duì)象践盼。然后鸦采,將這個(gè)對(duì)象與基本類(lèi)型值 true 構(gòu)成了邏輯與表達(dá)式。在布爾運(yùn)算中咕幻,false && true 等于 false渔伯。可是肄程,示例中的這行代碼是對(duì) falseObject 而不是對(duì)它的值(false)進(jìn)行求值锣吼。前面討論過(guò)选浑,布爾表達(dá)式中的所有對(duì)象都會(huì)被轉(zhuǎn)換為 true,因此 falseObject 對(duì)象在布爾表達(dá)式中代表的是 true玄叠。結(jié)果古徒,true && true 當(dāng)然就等于 true 了。
??基本類(lèi)型與引用類(lèi)型的布爾值還有兩個(gè)區(qū)別:
- typeof 操作符對(duì)基本類(lèi)型返回 "boolean"读恃,而對(duì)引用類(lèi)型返回 "object"描函。
- 由于 Boolean 對(duì)象是 Boolean 類(lèi)型的實(shí)例,所以使用 instanceof 操作符測(cè)試 Boolean 對(duì)象會(huì)返回 true狐粱,而測(cè)試基本類(lèi)型的布爾值則返回 false。
示例:
let falseObject = new Boolean(false);
let falseValue = false;
console.log(typeof falseObject); // object
console.log(typeof falseValue); // boolean
console.log(falseObject instanceof Boolean); // true
console.log(falseValue instanceof Boolean); // false
建議:永遠(yuǎn)不要使用 Boolean 對(duì)象胆数。
6.2肌蜻、Number 類(lèi)型
??Number 是與數(shù)字值對(duì)應(yīng)的引用類(lèi)型。要?jiǎng)?chuàng)建 Number 對(duì)象必尼,可以在調(diào)用 Number 構(gòu)造函數(shù)時(shí)向其中傳遞相應(yīng)的數(shù)值蒋搜。示例:
let numberObject = new Number(10);
Number 類(lèi)型的實(shí)例:
- 重寫(xiě)了 valueOf() 方法,返回對(duì)象表示的基本類(lèi)型的數(shù)值判莉;
- 重寫(xiě)了 toString() 方法豆挽,返回字符串形式的數(shù)值;
- 重寫(xiě)了 toLocaleString() 方法券盅,返回字符串形式的數(shù)值帮哈。
let num = new Number(10);
console.log(num.valueOf()); // 10
console.log(typeof num.valueOf()); // number
console.log(num.toString()); // 10
console.log(typeof num.toString()); // string
console.log(num.toLocaleString()); // 10
console.log(typeof num.toLocaleString()); // string
??可以為 toString()方法傳遞一個(gè)表示基數(shù)的參數(shù),告訴它返回幾進(jìn)制
數(shù)值的字符串形式锰镀。示例:
let num = 10;
console.log(num.toString()); // "10"
console.log(num.toString(2)); // "1010"
console.log(num.toString(8)); // "12"
console.log(num.toString(10)); // "10"
console.log(num.toString(16)); // "a"
??除了繼承的方法之外娘侍,Number 類(lèi)型還提供了一些用于將數(shù)值格式化為字符串的方法:
- toFixed():會(huì)按照指定的小數(shù)位返回?cái)?shù)值的字符串表示。
- toExponential():返回以指數(shù)表示法(也稱(chēng) e 表示法)表示的數(shù)值的字符串形式泳炉。
- toPrecision():返回表示某個(gè)數(shù)值的最合適的格式憾筏。
toFixed()
let num = 10;
console.log(num.toFixed(2)); // "10.00"
??這里給 toFixed() 方法傳入了數(shù)值 2,意思是顯示幾位小數(shù)花鹅。于是氧腰,這個(gè)方法返回了 "10.00",即以 0 填補(bǔ)了必要的小數(shù)位刨肃。如果數(shù)值本身包含的小數(shù)位比指定的還多古拴,那么接近指定的最大小數(shù)位的值就會(huì)舍入。示例:
let num = 10.005;
console.log(num.toFixed(2)); // "10.01"
??能夠自動(dòng)舍入的特性之景,使得 toFixed()方法很適合處理貨幣值斤富。
toExponential()
??toExponential() 接收一個(gè)參數(shù),該參數(shù)指定輸出結(jié)果中的小數(shù)位數(shù)锻狗。示例:
let num = 10;
console.log(num.toExponential(1)); // "1.0e+1"
toPrecision()
??對(duì)于一個(gè)數(shù)值來(lái)說(shuō)满力,toPrecision() 方法可能會(huì)返回固定大谢啦巍(fixed)格式,也可能返回指數(shù)(exponential)格式油额;具體規(guī)則是看哪種格式最合適叠纷。
??toPrecision() 方法接收一個(gè)參數(shù),即表示數(shù)值的所有數(shù)字的位數(shù)(不包括指數(shù)部分)潦嘶。示例:
let num = 99;
console.log(num.toPrecision(1)); // "1e+2"
console.log(num.toPrecision(2)); // "99"
console.log(num.toPrecision(3)); // "99.0"
??toPrecision() 會(huì)根據(jù)要處理的數(shù)值決定到底是調(diào)用 toFixed() 還是調(diào)用toExponential()涩嚣。而這三個(gè)方法都可以通過(guò)向上或向下舍入,做到以最準(zhǔn)確的形式來(lái)表示帶有正確小數(shù)位的值掂僵。
??在使用 typeof 操作符測(cè)試基本類(lèi)型數(shù)值時(shí)航厚,始終會(huì)返回 "number",而在測(cè)試 Number 對(duì)象時(shí)锰蓬,則會(huì)返回 "object"幔睬。類(lèi)似地,Number 對(duì)象是 Number 類(lèi)型的實(shí)例芹扭,而基本類(lèi)型的數(shù)值則不是麻顶。
let numberObject = new Number(10);
let numberValue = 10;
console.log(typeof numberObject); // "object"
console.log(typeof numberValue); // "number"
console.log(numberObject instanceof Number); // true
console.log(numberValue instanceof Number); // false
6.3、String 類(lèi)型
??**String 類(lèi)型是字符串對(duì)應(yīng)的引用類(lèi)型舱卡。示例:
let stringObject = new String("hello world");
String 類(lèi)型的實(shí)例:
- 重寫(xiě)了 valueOf() 方法辅肾,返回對(duì)象所表示的基本字符串值;
- 重寫(xiě)了 toString() 方法轮锥,返回對(duì)象所表示的基本字符串值矫钓;
- 重寫(xiě)了 toLocaleString() 方法,返回對(duì)象所表示的基本字符串值舍杜。
let str = new String('hello world');
console.log(str.valueOf()); // "hello world"
console.log(typeof str.valueOf()); // string
console.log(str.toString()); // "hello world"
console.log(typeof str.toString()); // string
console.log(str.toLocaleString()); // "hello world"
console.log(typeof str.toLocaleString()); // string
??String 類(lèi)型的每個(gè)實(shí)例都有一個(gè) length 屬性份汗,表示字符串中包含多個(gè)字符。示例:
let stringValue = "hello world";
console.log(stringValue.length); // "11"
注意:即使字符串中包含雙字節(jié)字符(不是占一個(gè)字節(jié)的 ASCII 字符)蝴簇,每個(gè)字符也仍然算一個(gè)字符杯活。
??String 類(lèi)型提供了很多方法,用于輔助完成對(duì) ECMAScript 中字符串的解析和操作熬词。
- 字符方法
- charAt() :返回給定位置的字符旁钧。
- charCodeAt():返回給定位置的字符的字符編碼。
- stringValue():返回給定位置的字符互拾。
- 字符串操作方法
- concat():將一或多個(gè)字符串拼接起來(lái)歪今,返回拼接得到的新字符串。
- slice():返回被操作字符串的一個(gè)子字符串颜矿。
- substr():返回被操作字符串的一個(gè)子字符串寄猩。
- substring():返回被操作字符串的一個(gè)子字符串。
- 字符串位置方法
- indexOf():從前向后搜索骑疆,返回字符串中指定字符串的位置田篇。
- lastIndexOf():從后向前搜索替废,返回字符串中指定字符串的位置。
- trim() 方法
- trim():會(huì)創(chuàng)建一個(gè)字符串的副本泊柬,刪除前置及后綴的所有空格椎镣,然后返回結(jié)果。
- 字符串大小寫(xiě)轉(zhuǎn)換方法
- toLowerCase():將字符串全部轉(zhuǎn)換成小寫(xiě)兽赁。
- toLocaleLowerCase():針對(duì)特定地區(qū)状答,將字符串全部轉(zhuǎn)換成小寫(xiě)。
- toUpperCase():將字符串全部轉(zhuǎn)換成大寫(xiě)刀崖。
- toLocaleUpperCase():針對(duì)特定地區(qū)惊科,將字符串全部轉(zhuǎn)換成大寫(xiě)。
- 字符串的模式匹配方法
- match():返回匹配項(xiàng)信息的數(shù)組亮钦。
- search():返回字符串中第一個(gè)匹配項(xiàng)的索引译断;如果沒(méi)有找到匹配項(xiàng),則返回 -1或悲。
- replace():進(jìn)行子字符串的替換操作。
- split():基于指定的分隔符將一個(gè)字符串分割成多個(gè)子字符串堪唐,并將結(jié)果放在一個(gè)數(shù)組中巡语。
- localeCompare() 方法
- localeCompare():用于比較兩個(gè)字符串。
- fromCharCode() 方法
- fromCharCode():
- HTML 方法
1. 字符方法
charAt() 方法接收一個(gè)參數(shù)淮菠,即基于 0 的字符位置男公,以單字符字符串的形式返回指定位置的字符。示例:
let stringValue = "hello world";
console.log(stringValue.charAt(1)); // "e"
charCodeAt() 方法接收一個(gè)參數(shù)合陵,即基于 0 的字符位置枢赔,返回給定位置的字符的字符編碼。示例:
let stringValue = "hello world";
console.log(stringValue.charCodeAt(1)); // "101"
stringValue() 方法使用方括號(hào)加數(shù)字索引來(lái)訪(fǎng)問(wèn)字符串中的特定字符拥知。示例:
let stringValue = "hello world";
console.log(stringValue[1]); // "e"
2. 字符串操作方法
concat() 方法用于將一或多個(gè)字符串拼接起來(lái)踏拜,返回拼接得到的新字符串。示例:
let stringValue = "hello ";
let result = stringValue.concat("world", "!");
console.log(result); // "hello world!"
console.log(stringValue); // "hello"
slice() 方法會(huì)返回被操作字符串的一個(gè)子字符串低剔。接收參數(shù):指定子字符串的開(kāi)始位置速梗,(可選)子字符串最后一個(gè)字符后面的位置(默認(rèn):到字符串末尾)。當(dāng)參數(shù)是負(fù)值時(shí)襟齿,slice() 方法會(huì)將傳入的負(fù)值與字符串的長(zhǎng)度相加姻锁。
substr() 方法會(huì)返回被操作字符串的一個(gè)子字符串。接收參數(shù):指定子字符串的開(kāi)始位置猜欺,(可選)返回的字符個(gè)數(shù)(默認(rèn):到字符串末尾)位隶。當(dāng)參數(shù)是負(fù)值時(shí),substr() 方法將負(fù)的第一個(gè)參數(shù)加上字符串的長(zhǎng)度开皿,而將負(fù)的第二個(gè)參數(shù)轉(zhuǎn)換為 0涧黄。
substring() 方法會(huì)返回被操作字符串的一個(gè)子字符串篮昧。接收參數(shù):指定子字
符串的開(kāi)始位置,(可選)子字符串最后一個(gè)字符后面的位置(默認(rèn):到字符串末尾)弓熏。當(dāng)參數(shù)是負(fù)值時(shí)恋谭,substring() 方法會(huì)把所有負(fù)值參數(shù)都轉(zhuǎn)換為 0。
let stringValue = "hello world"; // length === 11
console.log(slice(3)); // "lo world"
console.log(substr(3)); // "lo world"
console.log(substring(3)); // "lo world"
console.log(slice(3, 7)); // "lo w"
console.log(substr(3, 7)); // "lo worl"
console.log(substring(3, 7)); // "lo w"
console.log(slice(-3)); // "rld" (8)
console.log(substr(-3)); // "rld" (8)
console.log(substring(-3)); // "hello world" (0)
console.log(slice(3, -4)); // "lo w" (3, 7)
console.log(substr(3, -4)); // ""(空字符串) (0, 0)
console.log(substring(3, -4)); // "hel" (3, 0)
3. 字符串位置方法
indexOf() 方法從字符串的開(kāi)頭向后搜索指定的子字符串挽鞠,然后返回子字符串的位置(如果沒(méi)有找到該子字符串疚颊,則返回-1)。接收參數(shù):指定字符串信认,(可選)開(kāi)始搜索的位置(indexOf() 會(huì)從該參數(shù)指定的位置向后搜索材义,忽略該位置之前的所有字符)。
lastIndexOf() 方法從字符串的末尾向前搜索指定的子字符串嫁赏,然后返回子字符串的位置(如果沒(méi)有找到該子字符串其掂,則返回-1)。接收參數(shù):指定字符串潦蝇,(可選)開(kāi)始搜索的位置(lastIndexOf() 會(huì)從指定的位置向前搜索款熬,忽略該位置之后的所有字符)。
let stringValue = "hello world";
console.log(stringValue.indexOf("o")); // 4
console.log(stringValue.lastIndexOf("o")); // 7
console.log(stringValue.indexOf("o", 6)); // 7
console.log(stringValue.lastIndexOf("o", 6)); // 4
??在使用第二個(gè)參數(shù)的情況下攘乒,可以通過(guò)循環(huán)調(diào)用 indexOf() 或 lastIndexOf() 來(lái)找到所有匹配的子字符串贤牛。示例:
let stringValue = "Lorem ipsum dolor sit amet, consectetur adipisicing elit";
let positions = new Array();
let pos = stringValue.indexOf("e");
while(pos > -1){
positions.push(pos);
pos = stringValue.indexOf("e", pos + 1);
}
console.log(positions); // [3, 24, 32, 35, 52]
??這個(gè)例子通過(guò)不斷增加 indexOf() 方法開(kāi)始查找的位置,遍歷了一個(gè)長(zhǎng)字符串则酝。在循環(huán)之外殉簸,首先找到了 "e" 在字符串中的初始位置;而進(jìn)入循環(huán)后沽讹,則每次都給 indexOf() 傳遞上一次的位置加 1般卑。這樣,就確保了每次新搜索都從上一次找到的子字符串的后面開(kāi)始爽雄。每次搜索返回的位置依次被保存在數(shù)組 positions 中蝠检,以便將來(lái)使用。
4. trim() 方法
trim() 方法會(huì)創(chuàng)建一個(gè)字符串的副本挚瘟,刪除前置及后綴的所有空格蝇率,然后返回結(jié)果。由于 trim()返回的是字符串的副本刽沾,所以原始字符串中的前置及后綴空格會(huì)保持不變本慕。示例:
let stringValue = " hello world ";
let trimmedStringValue = stringValue.trim();
console.log(stringValue); // " hello world "
console.log(trimmedStringValue); // "hello world"
5. 字符串大小寫(xiě)轉(zhuǎn)換方法
??涉及字符串大小寫(xiě)轉(zhuǎn)換的方法有 4 個(gè):toLowerCase()、toLocaleLowerCase()侧漓、toUpperCase() 和 toLocaleUpperCase()锅尘。
??toLocaleLowerCase() 和 toLocaleUpperCase() 方法是針對(duì)特定地區(qū)的實(shí)現(xiàn)。一般來(lái)說(shuō),在不知道自己的代碼將在哪種語(yǔ)言環(huán)境中運(yùn)行的情況下藤违,還是使用針對(duì)地區(qū)的方法更穩(wěn)妥一些浪腐。
let stringValue = "hello world";
console.log(stringValue.toLocaleUpperCase()); // "HELLO WORLD"
console.log(stringValue.toUpperCase()); // "HELLO WORLD"
console.log(stringValue.toLocaleLowerCase()); // "hello world"
console.log(stringValue.toLowerCase()); // "hello world"
6. 字符串的模式匹配方法
??match() 只接受一個(gè)參數(shù),一個(gè)正則表達(dá)式 / 一個(gè) RegExp 對(duì)象顿乒。返回一個(gè)數(shù)組议街。在字符串上調(diào)用這個(gè)方法,本質(zhì)上與調(diào)用 RegExp 的 exec() 方法相同璧榄。示例:
let text = "cat, bat, sat, fat";
let pattern = /.at/;
//與 pattern.exec(text) 相同
let matches = text.match(pattern);
console.log(matches.index); // 0
console.log(matches[0]); // "cat"
console.log(pattern.lastIndex); // 0
??上述示例中的 match() 方法返回一個(gè)數(shù)組特漩;如果調(diào)用 RegExp 對(duì)象的 exec() 方法并傳遞本例中的字符串作為參數(shù),那么也會(huì)得到與此相同的數(shù)組:數(shù)組的第一項(xiàng)是與整個(gè)模式匹配的字符串骨杂,之后的每一項(xiàng)(如果有)保存著與正則表達(dá)式中的捕獲組匹配的字符串涂身。
??search() 只接受一個(gè)參數(shù),由字符串或 RegExp 對(duì)象指定的一個(gè)正則表達(dá)式搓蚪。返回字符串中第一個(gè)匹配項(xiàng)的索引蛤售;如果沒(méi)有找到匹配項(xiàng),則返回 -1妒潭。search() 方法始終是從前向后查找悴能。示例:
let text = "cat, bat, sat, fat";
let pos = text.search(/at/);
console.log(pos); // 1
??replace() 可以進(jìn)行子字符串的替換操作。接受 2 個(gè)參數(shù):一個(gè) RegExp 對(duì)象或者一個(gè)字符串(這個(gè)字符串不會(huì)被轉(zhuǎn)換成正則表達(dá)式)雳灾;一個(gè)字符串或者一個(gè)函數(shù)漠酿。
??如果第一個(gè)參數(shù)是字符串,那么只會(huì)替換第一個(gè)子字符串佑女。要想替換所有子字符串,唯一的辦法就是提供一個(gè)正則表達(dá)式谈竿,而且要指定全局(g)標(biāo)志团驱。示例:
let text = "cat, bat, sat, fat";
let result = text.replace("at", "ond");
console.log(result); // "cond, bat, sat, fat"
result = text.replace(/at/g, "ond");
console.log(result); // "cond, bond, sond, fond"
??如果第二個(gè)參數(shù)是字符串,那么還可以使用一些特殊的字符序列空凸,將正則表達(dá)式操作得到的值插入到結(jié)果字符串中嚎花。
字符序列 | 替換文本 |
---|---|
$$ | $ |
$& | 匹配整個(gè)模式的子字符串。與RegExp.lastMatch的值相同 |
$' | 匹配的子字符串之前的子字符串呀洲。與RegExp.leftContext的值相同 |
$` | 匹配的子字符串之后的子字符串紊选。與RegExp.rightContext的值相同 |
$n | 匹配第n個(gè)捕獲組的子字符串,其中n等于0~9道逗。例如兵罢,$1是匹配第一個(gè)捕獲組的子字符串,$2是匹配第二個(gè)捕獲組的子字符串滓窍,以此類(lèi)推卖词。如果正則表達(dá)式中沒(méi)有定義捕獲組,則使用空字符串 |
$nn | 匹配第nn個(gè)捕獲組的子字符串吏夯,其中nn等于01~99此蜈。例如即横,$01是匹配第一個(gè)捕獲組的子字符串,$02是匹配第二個(gè)捕獲組的子字符串裆赵,以此類(lèi)推东囚。如果正則表達(dá)式中沒(méi)有定義捕獲組,則使用空字符串 |
??通過(guò)這些特殊的字符序列战授,可以使用最近一次匹配結(jié)果中的內(nèi)容页藻,示例:
let text = "cat, bat, sat, fat";
let result = text.replace(/(.at)/g, "word ($1)");
console.log(result); // word (cat), word (bat), word (sat), word (fat)
??上述例子中,每個(gè)以"at"結(jié)尾的單詞都被替換了陈醒,替換結(jié)果是"word"后跟一對(duì)圓括號(hào)惕橙,而圓括號(hào)中是被
字符序列$1 所替換的單詞。
??如果第二個(gè)參數(shù)是函數(shù)钉跷。
??在只有一個(gè)匹配項(xiàng)(即與模式匹配的字符串)的情況下弥鹦,會(huì)向這個(gè)函數(shù)傳遞 3 個(gè)參數(shù):模式的匹配項(xiàng)、模式匹配項(xiàng)在字符串中的位置爷辙、原始字符串彬坏。
??在正則表達(dá)式中定義了多個(gè)捕獲組的情況下,傳遞給函數(shù)的參數(shù)依次是模式的匹配項(xiàng)膝晾、第一個(gè)捕獲組的匹配項(xiàng)栓始、第二個(gè)捕獲組的匹配項(xiàng)……,但最后兩個(gè)參數(shù)仍然分別是模式的匹配項(xiàng)在字符串中的位置血当、原始字符串幻赚。
??這個(gè)函數(shù)應(yīng)該返回一個(gè)字符串,表示應(yīng)該被替換的匹配項(xiàng)使用函數(shù)作為 replace() 方法的第二個(gè)參數(shù)可以實(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 """;
}
});
}
console.log(htmlEscape("<p class=\"greeting\">Hello world!</p>"));
// <p class="greeting">Hello world!</p>
??上述例子中落恼,我們?yōu)椴迦?HTML 代碼定義了函數(shù) htmlEscape(),這個(gè)函數(shù)能夠轉(zhuǎn)義 4 個(gè)字符:小于號(hào)离熏、大于號(hào)佳谦、雙引號(hào)、和號(hào)滋戳。钻蔑。實(shí)現(xiàn)這種轉(zhuǎn)義的最簡(jiǎn)單方式,就是使用正則表達(dá)式查找這幾個(gè)字符奸鸯,然后定義一個(gè)能夠針對(duì)每個(gè)匹配的字符返回特定 HTML 實(shí)體的函數(shù)咪笑。
??split() 方法基于指定的分隔符將一個(gè)字符串分割成多個(gè)子字符串,并將結(jié)果放在一個(gè)數(shù)組中娄涩。
??分隔符可以是字符串蒲肋,也可以是一個(gè) RegExp 對(duì)象(這個(gè)方法不會(huì)將字符串看成正則表達(dá)式)。
??split()方法可以接受可選的第二個(gè)參數(shù),用于指定數(shù)組的大小兜粘,以便確保返回的數(shù)組不會(huì)超過(guò)既定大小申窘。
示例:
let colorText = "red, blue, green, yellow";
let colors1 = colorText.split(","); // ["red", "blue", "green", "yellow"]
let colors2 = colorText.split(",", 2); // ["red", "blue"]
let colors3 = colorText.split(/[^\,]+/); // [" ", ",", ",", ",", " "]
/[^\,]+/:[^\,] 表示任何非,(逗號(hào))的字符,+ 表示一個(gè)或者多個(gè)孔轴。
??在最后一次調(diào)用 split() 返回的數(shù)組中剃法,第一項(xiàng)和最后一項(xiàng)是兩個(gè)空字符串。之所以會(huì)這樣路鹰,是因?yàn)橥ㄟ^(guò)正則表達(dá)式指定的分隔符出現(xiàn)在了字符串的開(kāi)頭(即子字符串 "red")和末尾(即子字符串 "yellow")贷洲。
7. localeCompare() 方法
localeCompare() 方法用于比較兩個(gè)字符串,并返回下列值中的一個(gè):
- 如果字符串在字母表中應(yīng)該排在字符串參數(shù)之前晋柱,則返回一個(gè)負(fù)數(shù)(大多數(shù)情況下是 -1优构,具體的值要視實(shí)現(xiàn)而定);
- 如果字符串等于字符串參數(shù)雁竞,則返回 0钦椭;
- 如果字符串在字母表中應(yīng)該排在字符串參數(shù)之后,則返回一個(gè)正數(shù)(大多數(shù)情況下是 1碑诉,具體的值同樣要視實(shí)現(xiàn)而定)彪腔。
示例:
let stringValue = "yellow";
console.log(stringValue.localeCompare("brick")); // 1
console.log(stringValue.localeCompare("yellow")); // 0
console.log(stringValue.localeCompare("zoo")); // -1
??強(qiáng)調(diào):因?yàn)?localeCompare() 返回的數(shù)值取決于實(shí)現(xiàn),所以最好是像下面例子所示的這樣使用這個(gè)方法进栽。
let stringValue = "yellow";
function determineOrder(value) {
let result = stringValue.localeCompare(value);
if (result < 0){
console.log("The string 'yellow' comes before the string '" + value + "'.");
} else if (result > 0) {
console.log("The string 'yellow' comes after the string '" + value + "'.");
} else {
console.log("The string 'yellow' is equal to the string '" + value + "'.");
}
}
determineOrder("brick");
// The string 'yellow' comes after the string 'brick'.
determineOrder("yellow");
// The string 'yellow' is equal to the string 'yellow'.
determineOrder("zoo");
// The string 'yellow' comes before the string 'zoo'.
8. fromCharCode() 方法
??fromCharCode() 方法是String 構(gòu)造函數(shù)本身的一個(gè)一個(gè)靜態(tài)方法德挣。接收一或多個(gè)字符編碼,然后將它們轉(zhuǎn)換成一個(gè)字符串快毛。從本質(zhì)上來(lái)看格嗅,這個(gè)方法與實(shí)例方法 charCodeAt() 執(zhí)行的是相反的操作。示例:
console.log(String.fromCharCode(104, 101, 108, 108, 111));
// "hello"
9. HTML 方法
方 法 | 輸出結(jié)果 |
---|---|
anchor(name) | <a name= "name">string</a> |
big() | <big>string</big> |
bold() | <b>string</b> |
fixed() | <tt>string</tt> |
fontcolor(color) | <font color="color">string</font> |
fontsize(size) | <font size="size">string</font> |
italics() | <i>string</i> |
link(url) | <a href="url">string</a> |
small() | <small>string</small> |
strike() | <strike>string</strike> |
sub() | <sub/>string</sub/> |
sup() | <sup/>string</sup/> |
??注意:表格最后兩個(gè) sub() 唠帝、sup() 輸出結(jié)果中字母后斜杠(/)不是書(shū)寫(xiě)錯(cuò)誤屯掖,而是markdown 會(huì)自動(dòng)解析,不能正確展示没隘,故意為之懂扼。
使用方法:
let str="Hello world!"
console.log(str.big()); // <big>Hello world!</big>
console.log(str.anchor(name)); // <a name= "name">Hello world!</a>
7禁荸、單體內(nèi)置對(duì)象
??ECMA-262 對(duì)內(nèi)置對(duì)象的定義是:“由 ECMAScript 實(shí)現(xiàn)提供的右蒲、不依賴(lài)于宿主環(huán)境的對(duì)象,這些對(duì)象在 ECMAScript 程序執(zhí)行之前就已經(jīng)存在了赶熟。” 意思就是說(shuō),開(kāi)發(fā)人員不必顯式地實(shí)例化內(nèi)置對(duì)象尉剩,因?yàn)樗鼈円呀?jīng)實(shí)例化了面粮。
??前面我們已經(jīng)介紹了大多數(shù)內(nèi)置對(duì)象,例如Object、Array 和 String竹宋。
??ECMA-262 還定義了兩個(gè)單體內(nèi)置對(duì)象:Global 和 Math劳澄。
7.1、Global 對(duì)象
??Global(全局)對(duì)象可以說(shuō)是 ECMAScript 中最特別的一個(gè)對(duì)象了蜈七,因?yàn)椴还苣銖氖裁唇嵌壬峡疵氚危@個(gè)對(duì)象都是不存在的。
??ECMAScript 中的 Global 對(duì)象在某種意義上是作為一個(gè)終極的“兜底兒對(duì)象”來(lái)定義的飒硅。換句話(huà)說(shuō)砂缩,不屬于任何其他對(duì)象的屬性和方法,最終都是它的屬性和方法三娩。
??事實(shí)上庵芭,沒(méi)有全局變量或全局函數(shù);所有在全局作用域中定義的屬性和函數(shù)雀监,都是 Global 對(duì)象的屬性双吆。例如:isNaN()、isFinite()滔悉、parseInt() 伊诵、parseFloat(),實(shí)際上全都是 Global對(duì)象的方法回官。除此之外曹宴,Global 對(duì)象還包含其他一些方法。
1. URI 編碼方法
??Global 對(duì)象的 encodeURI() 和 encodeURIComponent() 方法可以對(duì) URI(Uniform Resource Identifiers歉提,通用資源標(biāo)識(shí)符)進(jìn)行編碼笛坦,以便發(fā)送給瀏覽器。
??有效的 URI 中不能包含某些字符苔巨,例如空格版扩。而這兩個(gè) URI 編碼方法就可以對(duì) URI 進(jìn)行編碼,它們用特殊的 UTF-8 編碼替換所有無(wú)效的字符侄泽,從而讓瀏覽器能夠接受和理解礁芦。
encodeURI() 主要用于整個(gè) URI
(例如,http://www.wrox.com/illegal value.html)悼尾。
encodeURIComponent() 主要用于對(duì) URI 中的某一段
(例如前面 URI 中的 illegal value.html)進(jìn)行編碼柿扣。
??區(qū)別:encodeURI() 不會(huì)對(duì)本身屬于 URI 的特殊字符進(jìn)行編碼,例如冒號(hào)闺魏、正斜杠未状、問(wèn)號(hào)和井字號(hào);encodeURIComponent( ) 則會(huì)對(duì)它發(fā)現(xiàn)的任何非標(biāo)準(zhǔn)字符進(jìn)行編碼析桥。示例:
let uri = "http://www.wrox.com/illegal value.html#start";
console.log(encodeURI(uri));
// "http://www.wrox.com/illegal%20value.html#start"
console.log(encodeURIComponent(uri));
// "http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.html%23start"
??使用 encodeURI() 編碼后的結(jié)果是除了空格之外的其他字符都原封不動(dòng)司草,只有空格被替換成了%20艰垂。而 encodeURIComponent() 方法則會(huì)使用對(duì)應(yīng)的編碼替換所有非字母數(shù)字字符。這也正是可以對(duì)整個(gè) URI 使用 encodeURI()埋虹,而只能對(duì)附加在現(xiàn)有 URI 后面的字符串使用 encodeURIComponent() 的原因所在猜憎。
??一般來(lái)說(shuō),我們使用 encodeURIComponent() 方法的時(shí)候要比使用
encodeURI() 更多搔课,因?yàn)樵趯?shí)踐中更常見(jiàn)的是對(duì)查詢(xún)字符串參數(shù)而不是對(duì)基礎(chǔ) URI 進(jìn)行編碼拉宗。
?? 與 encodeURI() 和 encodeURIComponent() 方法對(duì)應(yīng)的兩個(gè)方法分別是 decodeURI() 和 decodeURIComponent()。
decodeURI() 只能對(duì)使用 encodeURI() 替換的字符進(jìn)行解碼辣辫。
decodeURIComponent() 能夠解碼使用 encodeURIComponent() 編碼的所有字符旦事,即它可以解碼任何特殊字符的編碼。
示例:
let uri = "http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.html%23start";
console.log(decodeURI(uri));
// http%3A%2F%2Fwww.wrox.com%2Fillegal value.html%23start
console.log(decodeURIComponent(uri));
// http://www.wrox.com/illegal value.html#start
2. eval() 方法
?? eval() 方法就像是一個(gè)完整的 ECMAScript 解析器急灭,它只接受一個(gè)參數(shù)姐浮,即要執(zhí)行的 ECMAScript(或 JavaScript)字符串。示例:
eval("console.log('hi')");
// 等價(jià)于
console.log('hi');
??當(dāng)解析器發(fā)現(xiàn)代碼中調(diào)用 eval() 方法時(shí)葬馋,它會(huì)將傳入的參數(shù)當(dāng)作實(shí)際的 ECMAScript 語(yǔ)句來(lái)解析卖鲤,然后把執(zhí)行結(jié)果插入到原位置。
??通過(guò) eval() 執(zhí)行的代碼被認(rèn)為是包含該次調(diào)用的執(zhí)行環(huán)境的一部分畴嘶,因此被執(zhí)行的代碼具有與該執(zhí)行環(huán)境相同的作用域鏈蛋逾。這意味著通過(guò) eval() 執(zhí)行的代碼可以引用在包含環(huán)境中定義的變量,示例:
let msg = "hello world";
eval("console.log(msg)"); // "hello world"
??變量 msg 是在 eval() 調(diào)用的環(huán)境之外定義的窗悯,但其中調(diào)用的 console.log() 仍然能夠顯示 "hello world"区匣。這是因?yàn)樯厦娴诙写a最終被替換成了一行真正的代碼。
??同樣地蒋院,我們也可以在 eval() 調(diào)用中定義一個(gè)函數(shù)亏钩,然后再在該調(diào)用的外部代碼中引用這個(gè)函數(shù):
eval("function sayHi() { console.log('hi'); }");
sayHi(); // "hi"
??顯然,函數(shù) sayHi() 是在 eval() 內(nèi)部定義的欺旧。但由于對(duì) eval() 的調(diào)用最終會(huì)被替換成定義函數(shù)的實(shí)際代碼姑丑,因此可以在下一行調(diào)用 sayHi()。
??對(duì)于變量也一樣:
eval("let msg = 'hello world'; ");
console.log(msg); // "hello world"
??在 eval() 中創(chuàng)建的任何變量或函數(shù)都不會(huì)被提升辞友,因?yàn)樵诮馕龃a的時(shí)候栅哀,它們被包含在一個(gè)字符串中;它們只在 eval() 執(zhí)行的時(shí)候創(chuàng)建称龙。
??嚴(yán)格模式下留拾,在外部訪(fǎng)問(wèn)不到 eval() 中創(chuàng)建的任何變量或函數(shù),因此前面兩個(gè)例子都會(huì)導(dǎo)致錯(cuò)誤茵瀑。同樣间驮,在嚴(yán)格模式下躬厌,為 eval 賦值也會(huì)導(dǎo)致錯(cuò)誤:
"use strict";
eval = "hi"; // causes error
??能夠解釋代碼字符串的能力非常強(qiáng)大马昨,但也非常危險(xiǎn)竞帽。因此在使用 eval() 時(shí)必須極為謹(jǐn)慎,特別是在用它執(zhí)行用戶(hù)輸入數(shù)據(jù)的情況下鸿捧。否則屹篓,可能會(huì)有惡意用戶(hù)輸入威脅你的站點(diǎn)或應(yīng)用程序安全的代碼(即所謂的代碼注入)。
3. Global 對(duì)象的屬性
??Global 對(duì)象還包含一些屬性匙奴,例如:特殊的值undefined堆巧、NaN、Infinity都是 Global 對(duì)象的屬性泼菌。此外谍肤,所有原生引用類(lèi)型的構(gòu)造函數(shù),像 Object 和Function哗伯,也都是 Global 對(duì)象的屬性荒揣。
屬 性 | 說(shuō) 明 | 屬 性 | 說(shuō) 明 |
---|---|---|---|
undefined | 特殊值undefined | Date | 構(gòu)造函數(shù)Date |
NaN | 特殊值NaN | RegExp | 構(gòu)造函數(shù)RegExp |
Infinity | 特殊值Infinity | Error | 構(gòu)造函數(shù)Error |
Object | 構(gòu)造函數(shù)Object | EvalError | 構(gòu)造函數(shù)EvalError |
Array | 構(gòu)造函數(shù)Array | RangeError | 構(gòu)造函數(shù)RangeError |
Function | 構(gòu)造函數(shù)Function | ReferenceError | 構(gòu)造函數(shù)ReferenceError |
Boolean | 構(gòu)造函數(shù)Boolean | SyntaxError | 構(gòu)造函數(shù)SyntaxError |
String | 構(gòu)造函數(shù)String | TypeError | 構(gòu)造函數(shù)TypeError |
Number | 構(gòu)造函數(shù)Number | URIError | 構(gòu)造函數(shù)URIError |
4. window 對(duì)象
??ECMAScript 雖然沒(méi)有指出如何直接訪(fǎng)問(wèn) Global 對(duì)象,但 Web 瀏覽器都是將這個(gè)全局對(duì)象作為 window 對(duì)象的一部分加以實(shí)現(xiàn)的焊刹。因此系任,在全局作用域中聲明的所有變量和函數(shù),就都成為了 window 對(duì)象的屬性虐块。示例:
let color = "red";
function sayColor(){
console.log(window.color);
}
window.sayColor(); // "red"
??另一種取得 Global 對(duì)象的方法是使用以下代碼:
let global = function(){
return this;
}();
??以上代碼創(chuàng)建了一個(gè)立即調(diào)用的函數(shù)表達(dá)式俩滥,返回 this 的值。如前所述贺奠,在沒(méi)有給函數(shù)明確指定 this 值的情況下(無(wú)論是通過(guò)將函數(shù)添加為對(duì)象的方法霜旧,還是通過(guò)調(diào)用 call() 或 apply()),this 值等于 Global 對(duì)象儡率。而像這樣通過(guò)簡(jiǎn)單地返回 this 來(lái)取得 Global 對(duì)象颁糟,在任何執(zhí)行環(huán)境下都是可行的。
7.2喉悴、Math 對(duì)象
??ECMAScript 還為保存數(shù)學(xué)公式和信息提供了一個(gè)公共位置棱貌,即 Math 對(duì)象。與我們?cè)?JavaScript 直接編寫(xiě)的計(jì)算功能相比箕肃,Math 對(duì)象提供的計(jì)算功能執(zhí)行起來(lái)要快得多婚脱。Math 對(duì)象中還提供了輔助完成這些計(jì)算的屬性和方法。
1. Math 對(duì)象的屬性
??Math 對(duì)象包含的屬性大都是數(shù)學(xué)計(jì)算中可能會(huì)用到的一些特殊值勺像。下表列出了這些屬性障贸。
屬 性 | 說(shuō) 明 |
---|---|
Math.E | 自然對(duì)數(shù)的底數(shù),即常量 e 的值 |
Math.LN10 | 10 的自然對(duì)數(shù) |
Math.LN2 | 2 的自然對(duì)數(shù) |
Math.LOG2E | 以 2 為底e的對(duì)數(shù) |
Math.LOG10E | 以 10 為底e的對(duì)數(shù) |
Math.PI | π 的值 |
Math.SQRT1_2 | 1/2 的平方根(即 2 的平方根的倒數(shù)) |
Math.SQRT2 | 2 的平方根 |
2. min() 和 max() 方法
??min() 和 max() 方法用于確定一組數(shù)值中的最小值和最大值吟宦。這兩個(gè)方法都可以接收任意多個(gè)數(shù)值參數(shù)篮洁,示例:
let max = Math.max(3, 54, 32, 16);
console.log(max); // 54
let min = Math.min(3, 54, 32, 16);
console.log(min); // 3
??這兩個(gè)方法經(jīng)常用于避免多余的循環(huán)和在 if 語(yǔ)句中確定一組數(shù)的最大值。
??要找到數(shù)組中的最大或最小值殃姓,可以像下面這樣使用 apply() 方法袁波。示例:
let values = [1, 2, 3, 4, 5, 6, 7, 8];
let max = Math.max.apply(Math, values);
console.log(max); // 8
3. 舍入方法
??將小數(shù)值舍入為整數(shù)的方法:
- Math.ceil():執(zhí)行向上舍入瓦阐,即它總是將數(shù)值向上舍入為最接近的整數(shù);
- Math.floor():執(zhí)行向下舍入篷牌,即它總是將數(shù)值向下舍入為最接近的整數(shù)睡蟋;
- Math.round():執(zhí)行標(biāo)準(zhǔn)舍入,即它總是將數(shù)值四舍五入為最接近的整數(shù)(這也是我們?cè)跀?shù)學(xué)課上學(xué)到的舍入規(guī)則)枷颊。
示例:
console.log(Math.ceil(25.9)); // 26
console.log(Math.ceil(25.5)); // 26
console.log(Math.ceil(25.1)); // 26
console.log(Math.round(25.9)); // 26
console.log(Math.round(25.5)); // 26
console.log(Math.round(25.1)); // 25
console.log(Math.floor(25.9)); // 25
console.log(Math.floor(25.5)); // 25
console.log(Math.floor(25.1)); // 25
4. random() 方法
Math.random() 方法返回大于等于 0 小于 1 的一個(gè)隨機(jī)數(shù)戳杀。
利用 Math.random() 從某個(gè)整數(shù)范圍內(nèi)隨機(jī)選擇一個(gè)值。
值 = Math.floor(Math.random() * 可能值的總數(shù) + 第一個(gè)可能的值)
??公式中用到了 Math.floor() 方法夭苗,這是因?yàn)?Math.random() 總返回一個(gè)小數(shù)值信卡。而用這個(gè)小數(shù)值乘以一個(gè)整數(shù),然后再加上一個(gè)整數(shù)题造,最終結(jié)果仍然還是一個(gè)小數(shù)坐求。第一個(gè)可能的值規(guī)定隨機(jī)整數(shù)的最小值。示例:
// 1 ~ 10 之間的隨機(jī)整數(shù)
let num = Math.floor(Math.random() * 10 + 1);
// 2 ~ 10 之間的隨機(jī)整數(shù)
let num = Math.floor(Math.random() *9 + 2);
??多數(shù)情況下晌梨,都可以通過(guò)一個(gè)函數(shù)來(lái)計(jì)算可能值的總數(shù)和第一個(gè)可能的值桥嗤,例如:
function selectFrom(lowerValue, upperValue) {
let choices = upperValue - lowerValue + 1;
return Math.floor(Math.random() * choices + lowerValue);
}
let num = selectFrom(2, 10);
console.log(num); // 介于 2 和 10 之間(包括 2 和 10)的一個(gè)數(shù)值
??利用這個(gè)函數(shù),可以方便地從數(shù)組中隨機(jī)取出一項(xiàng)仔蝌,例如:
let colors = ["red", "green", "blue", "yellow", "black", "purple", "brown"];
let color = colors[selectFrom(0, colors.length-1)];
console.log(color); // 可能是數(shù)組中包含的任何一個(gè)字符串
5. 其他方法
方 法 | 說(shuō) 明 |
---|---|
Math.abs(num) | 返回 num 的絕對(duì)值 |
Math.exp(num) | 返回 Math.E 的 num 次冪 |
Math.log(num) | 返回 num 的自然對(duì)數(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 的正切值 |
??雖然 ECMA-262 規(guī)定了這些方法泛领,但不同實(shí)現(xiàn)可能會(huì)對(duì)這些方法采用不同的算法。畢竟敛惊,計(jì)算某個(gè)值的正弦渊鞋、余弦和正切的方式多種多樣。也正因?yàn)槿绱饲萍罚@些方法在不同的實(shí)現(xiàn)中可能會(huì)有不同的精度锡宋。
小結(jié)
??對(duì)象在 JavaScript 中被稱(chēng)為引用類(lèi)型的值,而且有一些內(nèi)置的引用類(lèi)型可以用來(lái)創(chuàng)建特定的對(duì)象特恬,現(xiàn)簡(jiǎn)要總結(jié)如下:
- 引用類(lèi)型與傳統(tǒng)面向?qū)ο蟪绦蛟O(shè)計(jì)中的類(lèi)相似执俩,但實(shí)現(xiàn)不同;
- Object 是一個(gè)基礎(chǔ)類(lèi)型癌刽,其他所有類(lèi)型都從 Object 繼承了基本的行為役首;
- Array 類(lèi)型是一組值的有序列表,同時(shí)還提供了操作和轉(zhuǎn)換這些值的功能显拜;
- Date 類(lèi)型提供了有關(guān)日期和時(shí)間的信息衡奥,包括當(dāng)前日期和時(shí)間以及相關(guān)的計(jì)算功能;
- RegExp 類(lèi)型是 ECMAScript 支持正則表達(dá)式的一個(gè)接口远荠,提供了最基本的和一些高級(jí)的正則表達(dá)式功能矮固。
??函數(shù)實(shí)際上是 Function 類(lèi)型的實(shí)例,因此函數(shù)也是對(duì)象譬淳;而這一點(diǎn)正是 JavaScript 最有特色的地方档址。由于函數(shù)是對(duì)象盹兢,所以函數(shù)也擁有方法,可以用來(lái)增強(qiáng)其行為辰晕。
??因?yàn)橛辛嘶景b類(lèi)型,所以 JavaScript 中的基本類(lèi)型值可以被當(dāng)作對(duì)象來(lái)訪(fǎng)問(wèn)确虱。三種基本包裝類(lèi)型分別是:Boolean含友、Number 和 String。以下是它們共同的特征:
- 每個(gè)包裝類(lèi)型都映射到同名的基本類(lèi)型校辩;
- 在讀取模式下訪(fǎng)問(wèn)基本類(lèi)型值時(shí)窘问,就會(huì)創(chuàng)建對(duì)應(yīng)的基本包裝類(lèi)型的一個(gè)對(duì)象,從而方便了數(shù)據(jù)操作宜咒;
- 操作基本類(lèi)型值的語(yǔ)句一經(jīng)執(zhí)行完畢惠赫,就會(huì)立即銷(xiāo)毀新創(chuàng)建的包裝對(duì)象。
??在所有代碼執(zhí)行之前故黑,作用域中就已經(jīng)存在兩個(gè)內(nèi)置對(duì)象:Global 和 Math儿咱。在大多數(shù) ECMAScript 實(shí)現(xiàn)中都不能直接訪(fǎng)問(wèn) Global 對(duì)象;不過(guò)场晶,Web 瀏覽器實(shí)現(xiàn)了承擔(dān)該角色的 window 對(duì)象混埠。全局變量和函數(shù)都是 Global 對(duì)象的屬性。Math 對(duì)象提供了很多屬性和方法诗轻,用于輔助完成復(fù)雜的數(shù)學(xué)計(jì)算任務(wù)钳宪。