本筆記匯總了作者認(rèn)為“JavaScript高級程序設(shè)計(jì)”這本書的前7章知識(shí)重點(diǎn),僅供參考。
小結(jié):
對象在JavaScript中被稱為援用類型的值,而且有1些內(nèi)置的援用類型可以用來創(chuàng)建特定的對象,現(xiàn)扼要總結(jié)以下:
- 援用類型與傳統(tǒng)面向?qū)ο蟪绦蛟O(shè)計(jì)中的類類似,但實(shí)現(xiàn)不同;
- Object是1個(gè)基礎(chǔ)類型,其他所有類型都從Object繼承了基本的行動(dòng);
- Array類型是1組值得有序列表,同時(shí)還提供了操作和轉(zhuǎn)換這些值的功能;
- Date類型提供了有關(guān)日期和時(shí)間的信息,包括當(dāng)前日期和時(shí)間和相干的計(jì)算功能;
- RegExp類型是ECMAScript支持正則表達(dá)式的1個(gè)接口,提供了最基本的和1些高級的正則表達(dá)式工功能。
函數(shù)實(shí)際上是Function類型的實(shí)例,因此函數(shù)也是對象;而這1點(diǎn)正是JavaScript最有特點(diǎn)的地方。由于函數(shù)是對象,所以函數(shù)也具有方法,可以用來增強(qiáng)其行動(dòng)。
由于有了基本包裝類型,所以JavaScript中的基本類型值可以被當(dāng)作對象來訪問。3種基本包裝類型分別是:Boolean、Number和String。以下是他們共同的特點(diǎn):
- 每一個(gè)包裝類型都映照到同名的基本類型;
- 在讀取模式下訪問基本類型值時(shí),就會(huì)創(chuàng)建對應(yīng)的基本包裝類型的1個(gè)對象,從而方便了數(shù)據(jù)的操作;
- 操作基本類型值的語句1經(jīng)履行終了,就會(huì)立即燒毀新創(chuàng)建的對象。
在所有代碼履行之前,作用域中就已存在兩個(gè)內(nèi)置對象:Global和Math。在大多數(shù)ECMAScript實(shí)現(xiàn)中都不能直接訪問Global對象;不過,Web閱讀器實(shí)現(xiàn)了承當(dāng)該角色的window對象。全局變量和函數(shù)都是Global對象的屬性。Math對象提供了很多屬性和方法,用于輔助完成復(fù)雜的數(shù)學(xué)計(jì)算任務(wù)。
ECMAScript從技術(shù)上講是1門面向?qū)ο笳Z言,但它不具有傳統(tǒng)的面向?qū)ο笳Z言所支持的類和接口等基本結(jié)構(gòu)。援用類型有時(shí)也被稱為對象定義,由于它們描寫的是1類對象所具有的屬性和方法。對象是某個(gè)特定援用類型的實(shí)例。
大多數(shù)援用類型值都是Object類型的實(shí)例,Object是ECMAScript中使用最多的1個(gè)類型。創(chuàng)建Object實(shí)例的方式有兩種。第1種是使用new操作符后跟Object構(gòu)造函數(shù),如
var person = new Object();
person.name = "Nicholas";
person.age = 29;
另外一種是使用對象字面量表示法,如
var person = {
name : "Nicholas",
age : 29
};
1般來講,訪問對象屬性時(shí)使用的都是點(diǎn)表示法,JavaScript中也能夠使用方括號(hào)表示法來訪問對象的屬性。如
alert(person["name"]); //"Nicholas"
alert(person.name); //"Nicholas"
ECMAScript中的數(shù)組與其他多數(shù)語言中的數(shù)組有著很大的區(qū)分。雖然ECMAScript數(shù)組與其他語言中的數(shù)組都是數(shù)據(jù)的有序列表,但與其他語言不同的是,ECMAScript數(shù)組的每項(xiàng)可以保存任何類型的數(shù)據(jù)。
表示方法
創(chuàng)建數(shù)組的基本方式有兩種。第1種是使用Array構(gòu)造函數(shù),如果預(yù)先知道數(shù)組要保存的項(xiàng)目數(shù)量,也能夠給構(gòu)造函數(shù)傳遞該數(shù)量,而該數(shù)量會(huì)自動(dòng)變成length屬性的值;給構(gòu)造函數(shù)傳遞值也能夠創(chuàng)建數(shù)組。如
var colors = new Array();//空數(shù)組
var colors = new Array(20);//創(chuàng)建1個(gè)包括3項(xiàng)的數(shù)組
var colors = new Array("red", "blue", "green");//創(chuàng)建1個(gè)包括3個(gè)字符串值的數(shù)組
var names = Array("Greg");//創(chuàng)建1個(gè)包括1個(gè)字符串值的數(shù)組
第2種是使用數(shù)組字面量表示法。如
var colors = ["red", "blue", "green"];//創(chuàng)建1個(gè)包括3個(gè)字符串的數(shù)組
var names = [];//創(chuàng)建1個(gè)空數(shù)組
var values = [1,2,];//忌諱,會(huì)創(chuàng)建1個(gè)包括2或3項(xiàng)的數(shù)組
var options = [, , , , ,];//忌諱,會(huì)創(chuàng)建1個(gè)包括5或6項(xiàng)的數(shù)組
length屬性
數(shù)組length的屬性不是只讀的,通過設(shè)置這個(gè)屬性,可以從數(shù)組的末尾移除項(xiàng)或向數(shù)組中添加新項(xiàng)。
檢測數(shù)組
自從ECMAScript3作出規(guī)定后,就出現(xiàn)了肯定某個(gè)對象是否是數(shù)組的經(jīng)典問題。對1個(gè)網(wǎng)頁,或1個(gè)全局作用域而言,使用instanceof操作符就可以得到滿意結(jié)果。
if (value instanceof Array) {
//對數(shù)組履行某些操作
}
如果網(wǎng)頁中包括多個(gè)框架,那實(shí)際上就存在兩個(gè)以上不同的全局履行環(huán)境,從而存在兩個(gè)以上不同版本的Array構(gòu)造函數(shù)。如果從1個(gè)框架向另外一個(gè)框架傳入1個(gè)數(shù)組,那末傳入的數(shù)組與第2個(gè)框架中原生創(chuàng)建的數(shù)組分別具有各自不同的構(gòu)造函數(shù)。為了解決這個(gè)問題,ECMAScript5新增了Array.isArray()方法。
if (Array.isArray(value)) {
//對數(shù)組履行某些操作
}
轉(zhuǎn)換方法
toLocaleString() :
toString() :
valueOf() :
ECMAScript提供了1種讓數(shù)組的行動(dòng)類似于其他數(shù)據(jù)結(jié)構(gòu)的方法。
實(shí)現(xiàn)棧的方式(LIFO)
push()
: 棧中項(xiàng)插入pop()
:棧中項(xiàng)移除實(shí)現(xiàn)隊(duì)列的方法(FIFO)
push()
:向數(shù)組末端添加項(xiàng)shift()
:從數(shù)組前段獲得項(xiàng)數(shù)組中已存在兩個(gè)可以直接用來重排序的方法:reverse()
和sort()
方法。
reverse()
方法會(huì)反轉(zhuǎn)數(shù)組項(xiàng)的順序。
默許情況下,sort()
方法按升序排列數(shù)組項(xiàng)。為了實(shí)現(xiàn)排序,sort()
方法會(huì)調(diào)用每一個(gè)數(shù)組項(xiàng)的toString()
轉(zhuǎn)型方法,然后比較得到的字符串,以肯定如何排序。
另外,sort()
方法可以接收1個(gè)比較函數(shù)作為參數(shù)。比較函數(shù)接受兩個(gè)參數(shù),如果第1個(gè)參數(shù)應(yīng)當(dāng)位于第2個(gè)之前則返回1個(gè)負(fù)數(shù),如果兩個(gè)參數(shù)相等則返回0,如果第1個(gè)參數(shù)應(yīng)當(dāng)位于第2個(gè)以后則返回1個(gè)正數(shù)。實(shí)際操作可以根據(jù)需要自行定義。如最簡單的1個(gè)例子
function compare(value1, value2) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
只需將其作為參數(shù)傳遞給sort()
方法便可。
var values = [0, 1, 5, 10, 15];
values.sort(compare);
alert(values); //0, 1, 5, 10, 15
另外,對數(shù)值類型或其valueOf()
方法會(huì)返回?cái)?shù)值類型的對象類型,可使用1個(gè)更簡單的比較函數(shù)。
function compare(value1, value2) {
return value2 - value1;
}
ECMAScript為操作已包括在數(shù)組中的項(xiàng)提供了很多內(nèi)置方法。
concat()
:
該方法基于當(dāng)前數(shù)組的所有項(xiàng)創(chuàng)建1個(gè)新數(shù)組。在沒有參數(shù)時(shí)返回副本,接收參數(shù)會(huì)添加到數(shù)組末尾,如果接收的是數(shù)組,則數(shù)組每項(xiàng)添加到末尾。如
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ù)組的1或多個(gè)項(xiàng)創(chuàng)建1個(gè)新數(shù)組。slice()
方法接收1或兩個(gè)參數(shù),即要返回項(xiàng)的起始和結(jié)束位置。
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
splice()
:
該方法非常強(qiáng)大,用法很多。它的主要用處是向數(shù)組的中部插入項(xiàng),使用方式有3中:
splice(0, 2)
會(huì)刪除數(shù)組中的前兩項(xiàng)。splice(2, 0, "red", "green")
會(huì)從當(dāng)前數(shù)組的位置2開始插入字符串”red”和”green”。splice(2, 1, "red", "green")
會(huì)刪除當(dāng)前數(shù)組位置2的項(xiàng),然后再從當(dāng)前數(shù)組的位置2開始插入字符串”red”和”green”。splice()
方法始終都會(huì)返回1個(gè)數(shù)組,該數(shù)組中包括從原始數(shù)組中刪除的項(xiàng)(如果沒有刪除任何項(xiàng),則返回1個(gè)空數(shù)組)。下面的代碼展現(xiàn)了上述3中用法:
var colors = ["red", "green", "blue"];
var removed = colors.splice(0, 1); //刪除第1項(xiàng)
alert(colors); //green, blue
alert(removed); //red, 返回的數(shù)組中只包括1項(xiàng)
removed = colors.splice(1, 0, "yellow", "orange"); //從位置1開始插入兩項(xiàng)
alert(colors); //green, yellow, orange, blue
alert(removed); //返回的是1個(gè)空數(shù)組
removed = colors.splice(1, 1, "red", "purple"); //插入兩項(xiàng),刪除1項(xiàng)
alert(colors); //green, red, purple, orange, blue
alert(removed); //yellow, 返回的數(shù)組中只包括1項(xiàng)
ECMAScript5為數(shù)組實(shí)例添加了兩個(gè)位置方法:indexOf()
和lastIndexOf()
。這兩個(gè)方法都接受兩個(gè)參數(shù):要查找的項(xiàng)和(可選的)表示查找出發(fā)點(diǎn)位置的索引。不同的是,indexOf()
方法從數(shù)組的開頭向后查找,laseIndexOf()
方法則從數(shù)組的末尾開始向前查找。
這兩個(gè)方法都返回要查找的項(xiàng)在數(shù)組中的位置,沒找到返回⑴.在比較第1個(gè)參數(shù)與數(shù)組中的每項(xiàng)時(shí),會(huì)使用全等操作符;也就是說,要查找的項(xiàng)必須嚴(yán)格相等。
var person = { name: "Nicholas" };
var people = [{ name: "Nicholas" }];
var morePeople = [person];
alert(people.indexOf(person)); //⑴
alert(morePeople.indexOf(person)); //0
ECMAScript5為數(shù)組定義了5個(gè)迭代方法。每一個(gè)方法都接受兩個(gè)參數(shù):要在每項(xiàng)上運(yùn)行的函數(shù)和(可選的)運(yùn)行該函數(shù)的作用域——影響this的值。傳入這些方法中的函數(shù)會(huì)接收3個(gè)參數(shù):數(shù)組項(xiàng)的值、該想在數(shù)組中的位置和數(shù)組對象本身。根據(jù)使用的方法不同,這個(gè)函數(shù)履行后的返回值可能會(huì)也可能不會(huì)影響方法的返回值。以下是這5個(gè)迭代方法的作用。
every()
:對數(shù)組中的每項(xiàng)運(yùn)行給定函數(shù),如果該函數(shù)對每項(xiàng)都返回true,則返回true。some()
:對數(shù)組中的每項(xiàng)運(yùn)行給定函數(shù),如果該函數(shù)對任1項(xiàng)返回true,則返回true。filter()
:對數(shù)組中的每項(xiàng)運(yùn)行給定函數(shù),返回該函數(shù)會(huì)返回true的項(xiàng)組成的數(shù)組。forEach()
:對數(shù)組中的每項(xiàng)運(yùn)行給定函數(shù)。這個(gè)方法沒有返回值。map()
:對數(shù)組中的每項(xiàng)運(yùn)行給定函數(shù),返回每次函數(shù)調(diào)用的結(jié)果組成的數(shù)組。以上方法都不會(huì)修改數(shù)組中的包括的值。
其中,every()
和filter()
方法最類似。
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
filter()
簡稱為濾波器,作用也有點(diǎn)類似濾波器。可以用來過濾出符合條件項(xiàng)。
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]
map()
可以用來創(chuàng)建包括的項(xiàng)與另外一個(gè)數(shù)組逐一對應(yīng)的項(xiàng)。
var numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var mapResult = numbers.filter(function(item, index, array) {
return item * 2;
});
alert(mapResult); //[2, 4, 6, 8, 10, 8, 6, 4, 2]
forEach()
本質(zhì)上和使用for循環(huán)迭代數(shù)組1樣。
var numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
numbers.forEach(function(item, index, array) {
//履行某些操作
});
ECMAScript5還新增了兩個(gè)歸并數(shù)組的方法:reduce()
和reduceRight()
。這兩個(gè)方法都會(huì)迭代數(shù)組的所有項(xiàng),然后構(gòu)建1個(gè)終究返回的值。reduce()
從前到后,reduceRight()
從后到前。
這兩個(gè)方法都接收兩個(gè)參數(shù):1個(gè)在每項(xiàng)上調(diào)用的函數(shù)和(可選的)作為歸并基礎(chǔ)的初始值。傳給reduce()
和reduceRight()
的函數(shù)接收4個(gè)參數(shù):前1個(gè)值、當(dāng)前值、項(xiàng)的索引和數(shù)組對象。這個(gè)函數(shù)返回的任何值都會(huì)作為第1個(gè)參數(shù)自動(dòng)傳給下1項(xiàng)。第1次迭代產(chǎn)生在數(shù)組的第2項(xiàng)上,因此第1個(gè)參數(shù)是數(shù)組的第1項(xiàng),第2個(gè)參數(shù)就是數(shù)組的第2項(xiàng)。
使用reduce()
方法可以履行數(shù)組中所有值求和操作。
var values = [1, 2, 3, 4, 5];
var sum = values.reduce(function(prev, cur, index, array) {
return prev + cur;
});
alert(sum); //15
ECMAScript中的Date類型是在初期Java中的java.util.Date類基礎(chǔ)上構(gòu)建的。為此,Date類型使用自UTC(Coordinated Universal Time,國際調(diào)和時(shí)間)1970年1月1日午夜(零時(shí))開始經(jīng)過的毫秒數(shù)來保存日期。
創(chuàng)建日期對象,使用new操作符和Date構(gòu)造函數(shù)便可。
var now = new Date()
無參數(shù)傳遞時(shí)自動(dòng)獲得系統(tǒng)當(dāng)前日期和時(shí)間。如果想根據(jù)特定日期時(shí)間創(chuàng)建日期對象,傳入該日期毫秒數(shù)。為簡化計(jì)算進(jìn)程,ECMPScript提供兩個(gè)方法:Date.parse()
和Date.UTC()
。
其中, Date.parse()
接收1個(gè)表示日期的字符串。ECMA⑵62沒有定義 Date.parse()
應(yīng)當(dāng)支持哪一種日期格式,因此這個(gè)方法的行動(dòng)因?qū)崿F(xiàn)而異,而且通過時(shí)因地區(qū)而異。將地區(qū)設(shè)置為美國的閱讀器通常都接受以下日期格式:
例如:
var someDate = new Date(Date.parse("May 25, 2004"));
如果傳入Date.parse()
方法的字符串不能表示日期,那末它會(huì)返回NaN。實(shí)際上,如果直接講字符串傳遞給Date構(gòu)造函數(shù),也會(huì)在后臺(tái)調(diào)用Date.parse()
。
Date.UTC()
方法一樣也返回表示日期的毫秒數(shù)。 Date.UTC()
的參數(shù)分別是年份、基于0的月份(0⑴1)、月中的哪1天、小時(shí)數(shù)(0⑵3)、分鐘、秒和毫秒數(shù)。前兩個(gè)參數(shù)是必須的,其他默許為0。
//GMT時(shí)間2000年1月1日午夜零時(shí)
var y2k = new Date(Date.UTC(2000, 0));
//GMT時(shí)間2005年5月5日下午5:55:55
var allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55));
與其他援用類型1樣,日期類型繼承了toLocaleString()
、toString()
和valueOf()
方法。Date類型的toLocaleString()
方法會(huì)依照與閱讀器設(shè)置的地區(qū)相適應(yīng)的格式返回日期和時(shí)間。valueOf()
不返回字符串,而是返回日期的毫秒表示。
Date類型還有1些專門用于將日期格式化為字符串的方法,以下:
toDateString()
——以特定于實(shí)現(xiàn)的格式顯示星期幾、月、日和年;toTimeString()
——以特定于時(shí)間的格式顯示時(shí)、分、秒和時(shí)區(qū);toLocaleDateString()
——以特定于地區(qū)的格式顯示星期幾、月、日和年;toLocaleTimeString()
——以特定于實(shí)現(xiàn)的格式顯示時(shí)、分、秒;toUTCString()
——以特定于實(shí)現(xiàn)的格式顯示完全的UTC日期。其他相干日期/時(shí)間組件方法,可參考w3cschool的JavaScript Date對象
ECMAScript通過RegExp類型來支持正則表達(dá)式。
var expression = / pattern / flags ;
其中的模式(pattern)部份可以是任何簡單或復(fù)雜的正則表達(dá)式,可以包括字符類、限定符、分組、向前查找和反向援用。每一個(gè)正則表達(dá)式都可帶有1或多個(gè)標(biāo)志(flags),用以表明正則表達(dá)式的行動(dòng)。正則表達(dá)式匹配模式支持3個(gè)標(biāo)志。
與其他語言中的正則表達(dá)式類似,模式中使用的所有元字符都必須轉(zhuǎn)義。
關(guān)于正則表達(dá)式的基本介紹,參考菜鳥教程上的正則表達(dá)式教程。
另外,關(guān)于RegExp對象的介紹,可以參考w3cschool上的JavaScript RegExp對象。在這里,就不贅述了。不管哪1門語言,在對字符串的處理上,正則表達(dá)式都是1個(gè)強(qiáng)大的工具,1定需要掌握。
ECMAScript中最特殊確當(dāng)屬函數(shù)了,由于,函數(shù)實(shí)際上是對象!每一個(gè)函數(shù)都是Function類型的實(shí)例,而且和其他援用類型1樣具有屬性和方法。由于函數(shù)是對象,因此函數(shù)名實(shí)際上也是1個(gè)指向函數(shù)對象的指針,不會(huì)與某個(gè)函數(shù)綁定。
函數(shù)聲明與函數(shù)表達(dá)式
解析器在向履行環(huán)境中加載數(shù)據(jù)時(shí),對函數(shù)聲明和函數(shù)表達(dá)式并不是1視同仁。解析器會(huì)率先讀取函數(shù)聲明,并使其履行代碼之前可用(可以訪問);至于函數(shù)表達(dá)式,則必須等到解析器履行到它所在的代碼行,才會(huì)真正被解析履行。因此,除甚么時(shí)候可以通過變量訪問函數(shù)這1點(diǎn)區(qū)分外,函數(shù)聲明與函數(shù)表達(dá)式的語法實(shí)際上是等價(jià)的。
//使用函數(shù)聲明
alert(sum(10, 10));
function sum(num1, num2) {
return num1 + num2;
}
上例能夠正常運(yùn)行,由于在代碼履行前,解析器就已通過1個(gè)名為函數(shù)聲明提升(function declaration hoisting)的進(jìn)程,讀取并將函數(shù)聲明添加到履行環(huán)境中。對代碼求值時(shí),JavaScript引擎在第1遍會(huì)聲明函數(shù)并將他們放到源代碼樹的頂部。所以,即便聲明函數(shù)的代碼在調(diào)用它的帶碼后面,JavaScript引擎也能把函數(shù)聲明提升到頂部。而下例函數(shù)表達(dá)式則不能運(yùn)行
//使用函數(shù)表達(dá)式
alert(sum(10, 10));
var sum = function(num1, num2) {
return num1 + num2;
}
沒有重載!
由于函數(shù)是對象,函數(shù)名實(shí)際上是1個(gè)指向函數(shù)對象的指針,不會(huì)與某個(gè)函數(shù)綁定,這正是ECMAScript中沒有函數(shù)重載概念的緣由。個(gè)人理解,除此以外,由于ECMAScript中的變量為疏松類型,因此對傳入函數(shù)的參數(shù)類型沒法加以限制,因此沒法像C++或Java那樣根據(jù)傳入?yún)?shù)類型或數(shù)量選擇調(diào)用函數(shù),這也是造成ECMAScript沒法重載的緣由之1。
//函數(shù)聲明
function addSomeNumber(num) {
return num + 100;
}
function addSomeNumber(num) {
return num + 200;
}
var result = addSomeNumber(100); //300
該例聲明兩個(gè)同名函數(shù),結(jié)果是后面的函數(shù)覆蓋了前面的。該例與下面的代碼幾近沒有區(qū)分:
var addSomeNumber = function (num) {
return num + 100;
};
addSomeNumber = function (num) {
return num + 200;
};
var result = addSomeNumber(100); //300
作為返回值的函數(shù)
由于ECMAScript中的函數(shù)名本身就是變量,因此函數(shù)也能夠作為值來使用。便可以作為參數(shù)或返回值。
//函數(shù)作為參數(shù)
function callSomeFunction (someFunction, someArgument) {
return somFunction (someArgument);
}
function add10 (num) {
return num + 10;
}
var result1 = callSomeFunction (add10, 10);
alert(result1); //20
function getGreeting (name) {
return "Hello, " + name;
}
var result2 = callSomeFunction (getGreeting, "Nicholas");
alert(result2); //"Hello, Nicholas"
函數(shù)作為返回值是極有用的技術(shù),是“閉包”技術(shù)的基礎(chǔ)之1。
比較典型的如數(shù)組sort()方法的比較函數(shù),它需要接收兩個(gè)參數(shù),比較它們的值。可使假定有1個(gè)對象數(shù)組,要根據(jù)某個(gè)對象屬性排序,怎樣辦呢?
function createComparisonFunction (propertyName) {
return function (object1, object2) {
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
};
}
該函數(shù)接收1個(gè)屬性名,然后根據(jù)這個(gè)屬性名來創(chuàng)建1個(gè)比較函數(shù)。使用以下
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
函數(shù)內(nèi)部屬性(重點(diǎn))
在函數(shù)內(nèi)部,有兩個(gè)特殊的對象:arguments
和this
。
arguments的主要用處是保存函數(shù)參數(shù),這個(gè)對象還有1個(gè)名叫callee
的屬性,該屬性是1個(gè)指針,指向具有這個(gè)arguments
對象的函數(shù)。它可以完成函數(shù)體與函數(shù)名的解耦,以下面這個(gè)階乘函數(shù)的利用:
//與函數(shù)名牢牢耦合
function factorial (num) {
if (num <= 1) {
return 1;
} else {
return num * factorial (num - 1)
}
}
//使用arguments.callee替換函數(shù)名,消除耦合
function factorial (num) {
if (num <= 1) {
return 1;
} else {
return num * arguments.callee (num - 1)
}
}
這樣,不管援用函數(shù)時(shí)使用的是甚么名字,都可以保證正常完成遞歸調(diào)用。如
var trueFactorial = factorial;
factorial = function () {
return 0;
};
alert(trueFactiorial(5)); //120
alert(factorial(5)); //0
函數(shù)內(nèi)部另外一個(gè)特殊對象是this
,其行動(dòng)與Java和C#中的this
大致類似。即,this
援用的是函數(shù)據(jù)以履行的環(huán)境對象——或也能夠說是this
值(當(dāng)在網(wǎng)頁的全局作用域中調(diào)用函數(shù)時(shí),this
對象援用的就是window
)。以下例
window.color = "red";
var o = { color: "blue"};
function sayColor() {
alert(this.color);
}
sayColor(); //"red"
o.sayColor = sayColor;
o.sayColor(); //"blue"
sayColor()
在全局域中定義,當(dāng)在全局域中調(diào)用時(shí),this
援用的是全局對象window
;當(dāng)把這個(gè)函數(shù)賦給對象o
并調(diào)用o.sayColor()
是,this
援用的是對象o
。
ECMAScript 5也規(guī)范化了另外一個(gè)函數(shù)對象的屬性:caller
。這個(gè)屬性保存著調(diào)用當(dāng)前函數(shù)的函數(shù)的援用,如果是在全局域中調(diào)用當(dāng)前函數(shù),它的值為null
。使用方式類似于callee
,在此不贅述。
函數(shù)屬性和方法(重點(diǎn))
ECMAScript中函數(shù)是對象,因此也有屬性和方法。
每一個(gè)函數(shù)都包括兩個(gè)屬性:length
和prototype
。其中,length
表示函數(shù)希望接收的命名參數(shù)的個(gè)數(shù);對ECMAScript中的援用類型來講,prototype
是保存他們所有實(shí)例方法的真正所在。
諸如toString()
和valueOf()
等方法實(shí)際上都保存在prototype
名下,只不過是通過各自對象的實(shí)例訪問它們罷了。在創(chuàng)建自定義援用類型和實(shí)現(xiàn)繼承時(shí),prototype
屬性的作用極其重要。在ECMAScript 5中,prototype
屬性是不可枚舉的,因此使用for-in
沒法發(fā)現(xiàn)。
每一個(gè)函數(shù)都包括兩個(gè)非繼承而來的方法:apply()
和call()
。這兩個(gè)方法都是在特定的作用域中調(diào)用函數(shù),實(shí)際上等于設(shè)置函數(shù)體內(nèi)this
對象的值。
apply()
方法接收兩個(gè)參數(shù),1個(gè)是在其中運(yùn)行函數(shù)的作用域,另外一個(gè)是參數(shù)數(shù)組。其中,第2個(gè)參數(shù)可以是Array
的實(shí)例,也能夠是arguments
對象。例如
function sum(num1, num2) {
return num1 + num2;
}
function callSum1(num1, num2) {
return sum.apply(this, arguments); //傳入arguments對象
}
function callSum2(num1, num2) {
return sum.apply(this, [num1, num2]); //傳入數(shù)組
}
alert(callSum1(10, 10)); //20
alert(callSum2(10, 10)); //20
call()
方法與apply()
方法的作用相同,他們的區(qū)分僅在于接收參數(shù)的方式不同。對call()
方法而言,第1個(gè)參數(shù)是this
值沒有變化,變化的是其余參數(shù)都直接傳遞給函數(shù)。即,在使用call()
方法時(shí),傳遞給函數(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í)上,傳遞參數(shù)并不是apply()
和call()
真正用武之地,它們真正強(qiáng)大的地方是能夠擴(kuò)充函數(shù)賴以運(yùn)行的作用域。例如
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
ECMAScript 5還定義了1個(gè)方法:bind()
。這個(gè)方法會(huì)創(chuàng)建1個(gè)函數(shù)的實(shí)例,其this
值會(huì)被綁定到傳給bind()
函數(shù)的值。例如
window.color = "red";
var o = { color: "blue" };
function sayColor() {
alert(this.color);
}
var objectSayColor = sayColor.bind(o);
objectSayColor(); //blue
和Java類似,為了便于操作基本類型值,ECMAScript也提供了3個(gè)特殊的援用類型:Boolean
、Number
和String
。每當(dāng)讀取1個(gè)基本類型值的時(shí)候,后臺(tái)就會(huì)創(chuàng)建1個(gè)對應(yīng)的基本包裝類型的對象,從而讓我們能夠調(diào)用1些方法來操作這些數(shù)據(jù)。有點(diǎn)類似于Java的自動(dòng)拆裝箱進(jìn)程,以String
類型為例
var s1 = "some text";
var s2 = s1.substring(2);
在訪問s1
時(shí),訪問進(jìn)程處于讀取模式,后臺(tái)自動(dòng)完成以下處理:
String
類型的1個(gè)實(shí)例;以上3個(gè)步驟可以想象成以下代碼
var s1 = new String("some text");
var s2 = s1.substring(2);
s1 = null;
以上3個(gè)步驟一樣適用于Boolean
和Number
類型對應(yīng)的布爾值和數(shù)字值。
援用類型與基本包裝類型主要區(qū)分就是對象的生存期。使用new
操作符創(chuàng)建的援用類型的實(shí)例,在履行流離開當(dāng)前援用域之前1直都保存在內(nèi)存中。而自動(dòng)創(chuàng)建的基本包裝類型的對象,則只存在1行代碼的履行瞬間,然后立即燒毀。這意味著不能在運(yùn)行時(shí)為基本類型值添加屬性和方法。
Boolean
類型是與布爾值對應(yīng)的援用類型,建議永久不要使用Boolean
對象。
除繼承的方法外,Number
類型還提供了1些用于將數(shù)值格式化為字符串的方。
- toFixed()
:按指定小數(shù)位返回?cái)?shù)值的字符串表示。
- toExponential()
:返回以指數(shù)表示法表示的數(shù)值的字符串情勢。
- toPrecision()
:返回固定大小格式,也可能返回指數(shù)格式,具體規(guī)則是看哪一種格式比較適合。該方法接收1個(gè)參數(shù)指定表示數(shù)值的所有數(shù)字的位數(shù)。
String
類型提供了很多方法,用于輔助完成對ECMAScript中字符串的解析和操作。
字符方法
兩個(gè)用于訪問字符串中特定字符的方法時(shí):charAt()
和charCodeAt()
。兩個(gè)方法都接收1個(gè)參數(shù),即基于0餓字符位置。charAt()
返回指定位置字符,charCodeAt()
返回指定位置字符編碼。
字符串操作方法
concat()
:
用于將1或多個(gè)字符串拼接起來,接受任意多個(gè)參數(shù)。
slice()
、substr()
和substring()
:
這3個(gè)方法基于字符串創(chuàng)建新字符串。它們都會(huì)返回被操作字符串的1個(gè)子字符串,而且也都接受1或兩個(gè)參數(shù)。第1個(gè)參數(shù)指定子字符串的開始位置,第2個(gè)參數(shù)(在指定的情況下)表示子字符串到哪里結(jié)束。具體來講,slice()
和substr()
的第2個(gè)參數(shù)指定的是子字符串最后1個(gè)字符后面的位置。而substr()
的第2個(gè)參數(shù)指定的則是返回的字符數(shù)。如果沒有給這些方法傳遞第2個(gè)參數(shù),則將字符串的長度作為結(jié)束位置。
var StringObject = "hello world";
alert(StringObject .slice(3)); //輸出 "lo world"
alert(StringObject .substring(3)); //輸出 "lo world"
alert(StringObject .substr(3)); //輸出 "lo world"
alert(StringObject .slice(3, 7)); //輸出 "lo w"
alert(StringObject .substring(3, 7)); //輸出 "lo w"
alert(StringObject .substr(3, 7)); //輸出 "lo worl"
當(dāng)傳遞的參數(shù)是負(fù)值時(shí),它們的行動(dòng)就不盡相同了。其中,slice()
方法會(huì)將傳入的賦值與字符串長度相加,substr()
方法將負(fù)的第1個(gè)參數(shù)加上字符串的長度,而將負(fù)的第2個(gè)參數(shù)轉(zhuǎn)換為0.最后,substring()
方法會(huì)把所有負(fù)值參數(shù)都轉(zhuǎn)換為0.
var StringObject = "hello world";
alert(StringObject .slice(-3)); //輸出 "rld"
alert(StringObject .substring(-3)); //輸出 "hello world"
alert(StringObject .substr(-3)); //輸出 "rld"
alert(StringObject .slice(3, -4)); //輸出 "lo w"
alert(StringObject .substring(3, -4)); //輸出 "hel"
alert(StringObject .substr(3, -4)); //輸出 "" 空字符串
字符串位置方法
有兩個(gè)可以從字符串中查找子字符串的方法:indexOf()
和lastIndexOf()
。前者從前往后搜索,后者反之。
兩個(gè)方法都可接收可選的第2個(gè)參數(shù),表明從字符串哪一個(gè)位置開始搜索。
在使用第2個(gè)參數(shù)的情況下,可以通過循環(huán)調(diào)用indexOf()
或lastIndexOf()
來找到所有匹配的子字符串。以下:
var stringValue = "Lorem ipsum dolor sit amet, consectetur adipisicing elit";
var positions = new Array();
var pos = stringValue.indexOf("e");
while (pos > -1) {
positions.push(pos);
pos = stringValue.indexOf("e", pos + 1);
}
alert(positions); //"3, 24, 32, 35, 52"
trim()方法
該方法創(chuàng)建1個(gè)字符串的副本,刪除前置及后綴的所有空格,然后返回結(jié)果。
字符串大小寫轉(zhuǎn)換方法
ECMAScript中觸及字符串大小寫轉(zhuǎn)換的方法有4個(gè):toLowerCase()
、toLocaleLowerCase()
、toUpperCase()
和toLocaleUpperCase()
。
字符串的模式匹配方法
match()
:
在字符串上調(diào)用這個(gè)方法,本質(zhì)上與調(diào)用RegExp
的exec()
方法相同。match()
只接受1個(gè)參數(shù),正則表達(dá)式或RegExp
對象。和RegExp
對象的exec()
方法1樣,match()
方法會(huì)返回1個(gè)數(shù)組:數(shù)組的第1項(xiàng)是與全部模式匹配的字符串,以后的每項(xiàng)(如果有)保存著與正則表達(dá)式中的捕獲組匹配的字符串。
var text = "cat, bat, sat, fat";
var pattern = /.at/;
//與pattern.exec(text)相同
var matches = text.match(pattern);
alert(matches.index); //0
alert(matches[0]); //"cat"
alert(pattern.lastIndex); //0
search()
:
參數(shù)與match()
方法相同,返回字符串中第1個(gè)匹配項(xiàng)的索引,如果沒有返回⑴。
var text = "cat, bat, sat, fat";
var pos = text.search(/at/);
alert(pos); //1
replace()
:
接受兩個(gè)參數(shù),第1個(gè)參數(shù)可以是1個(gè)RegExp
對象或1個(gè)字符串(這個(gè)字符串不會(huì)被轉(zhuǎn)換為正則表達(dá)式),第2個(gè)參數(shù)可以是1個(gè)字符串或1個(gè)函數(shù)。如果第1個(gè)參數(shù)是字符串,那末只會(huì)替換第1個(gè)字符串,想替換所有字符串只能提供1個(gè)正則表達(dá)式,并且要指定全局(g)標(biāo)志。
var text = "cat, bat, sat, fat";
var result = text.replace("at", "ond");
alert(result); //"cond, bat, sond, fond"
如果第2個(gè)參數(shù)是字符串,那末還可使用1些特殊的字符序列,將正則表達(dá)式操作得到的值插入到結(jié)果字符串中。下表列出了ECMAScript提供的這些特殊的字符序列。
字符序列 | 替換文本 |
---|---|
$$ | $ |
$& | 匹配全部模式的子字符串。與RegExp.lastMatch的值相同 |
$’ | 匹配的子字符串之前的子字符串。與RegExp.leftContext的值相同 |
$` | 匹配的子字符串之前的子字符串。與RegExp.rightContext的值相同 |
$n | 匹配第n個(gè)捕獲組的子字符組,其中nn等于0~9。例如,$1是匹配第1個(gè)捕獲組的子字符串,$2是匹配第2個(gè)捕獲組的子字符串,以此類推。如果正則表達(dá)式中沒有定義捕獲組,則使用空字符串 |
$nn | 匹配第nn個(gè)捕獲組的子字符串,其中nn等于01~99。例如$01是匹配第1個(gè)捕獲組的子字符串,$02是匹配第2個(gè)捕獲組的子字符串,以此類推。如果正則表達(dá)式中沒有定義捕獲組,則使用空字符串 |
通過這些特殊的字符序列,可使用最近1次匹配結(jié)果中的內(nèi)容,以下
var text = "cat, bat, sat, fat";
result = text.replace(/(.at)/g, "word ($1)");
alert(result); //word (cat), word (bat), word(sat), word (fat)
replace()
方法的第2個(gè)參數(shù)也能夠是1個(gè)函數(shù)。在只有1個(gè)匹配項(xiàng)(即與模式匹配的字符串)的情況下,會(huì)向這個(gè)函數(shù)傳遞3個(gè)參數(shù):模式的匹配項(xiàng)、模式匹配項(xiàng)在字符串中的位置和原始字符串。在正則表達(dá)式定義了多個(gè)捕獲組的情況下,傳遞給函數(shù)的參數(shù)1次是模式的匹配項(xiàng)、第1個(gè)捕獲組的匹配項(xiàng)、第2個(gè)捕獲組的匹配項(xiàng)……,但最后兩個(gè)參數(shù)依然分別是模式的匹配項(xiàng)在字符串中的位置和原始字符串。這個(gè)函數(shù)應(yīng)當(dāng)返回1個(gè)字符串,表示應(yīng)當(dāng)被替換的匹配項(xiàng)使用函數(shù)作為replace()
方法的第2個(gè)參數(shù)可以實(shí)現(xiàn)更加精細(xì)的替換操作,以下例
\\返回html實(shí)體
function htmlEscape(text) {
return text.replace(/[<>"&]/g, function(match, pos, originalText) {
switch(match) {
case "<":
return "<";
case ">":
return ">";
case "&":
return "&";
case "\"":
return """
}
});
}
alert(htmlEscape("<p class=\"greeting\">Hello world!</p>"));
//<p class="greeting">Hello world!</p>
split()
:
該方法可以基于指定的分隔符將1個(gè)字符串分割成多個(gè)子字符串,并將結(jié)果放在1個(gè)數(shù)組中。分隔符可以是字符串,也能夠是1個(gè)RegExp
對象(這個(gè)方法不會(huì)將字符串看成正則表達(dá)式)。split()
方法可以接受可選的第2個(gè)參數(shù),用于指定數(shù)組的大小,以便確保返回的數(shù)組不會(huì)超過既定大小。
var colorText = "red, blue, green, yellow";
var colors1 = colorText.split(","); //["red", "blue", "green", "yellow"]
var colors2 = colorText.split(",", 2); //["red", "blue"]
var colors3 = colorText.split(/[^\,]+/); //["", ",", ",", ",", ""]
localeCompare()方法
該方法比較兩個(gè)字符串,并返回以下值中的1個(gè):
var stringValue = "yellow";
alert(stringValue.localeCompare("brick")); //1
alert(stringValue.localeCompare(