javascript
《JavaScript高级程序设计(第四版)》红宝书学习笔记(第五章:基本引用类型,原始值包装类型,单例内置对象)
第五章:基本引用類型
引用值(或者對象)是某個(gè)特定引用類型的實(shí)例。新對象通過使用new操作符后跟一個(gè)構(gòu)造函數(shù)(constructor)來創(chuàng)建。
5.1 Date
這里不對Date進(jìn)行詳細(xì)深入,僅基于書本列出一些常用方法。更多方法和用法請參考:https://www.runoob.com/jsref/jsref-obj-date.html。
1)基于其他其他日期和時(shí)間創(chuàng)建日期對象:
Date.parse 和 Date.UTC
Date.now 返回表示方法執(zhí)行日期和時(shí)間的毫秒數(shù)。
2)繼承的方法:
Date類型重寫了 toLocaleString() 、toString() 、valueOf() 方法。
-
toLocaleString() 方法返回與瀏覽器運(yùn)行的本地環(huán)境一致的日期和時(shí)間。
-
toString() 方法通常返回帶時(shí)區(qū)信息的日期和時(shí)間。
-
valueOf 被重寫后返回的是日期的毫秒表示。
3)日期格式化方法:
Date類型有幾個(gè)專門用于格式化日期的方法,它們都會返回字符串:
-
toDateString()顯示日期中的周幾、月、日、年(格式特定于實(shí)現(xiàn));
-
toTimeString() 顯示日期中的時(shí)、分、秒和時(shí)區(qū)(格式特定于實(shí)現(xiàn));
-
toLocaleDateString() 顯示日期中的周幾、月、日、年(格式特定于實(shí)現(xiàn)和地區(qū));tolocaleTimeString()顯示日期中的時(shí)、分、秒(格式特定于實(shí)現(xiàn));
-
toUTCString() 顯示完整的UTC日期(格式特定于實(shí)現(xiàn))。
這些方法的輸出與tolocaleString()和 tostring()一樣,會因?yàn)g覽器而異。因此不能用于在用戶界面上一致地顯示日期。
注意 還有一個(gè)方法叫 toGMTString(),這個(gè)方法跟 toUTCString() 是一樣的,目的
是為了向后兼容。不過,規(guī)范建議新代碼使用 toUTCString()。
4)日期/時(shí)間組件方法。
5.2 RegExp `
ECMAScript通過RegExp類型支持正則表達(dá)式。正則表達(dá)式使用類似Perl的簡潔語法來創(chuàng)建:
let expression = /pattern/flags;
這個(gè)正則表達(dá)式的pattern(模式)可以是任何簡單或復(fù)雜的正則表達(dá)式,包括字符類、限定符、分組、向前查找和反向引用。每個(gè)正則表達(dá)式可以帶零個(gè)或多個(gè) flags(標(biāo)記),用于控制正則表達(dá)式的行為。下面給出了表示匹配模式的標(biāo)記。
-
g:全局模式,表示查找字符串的全部內(nèi)容,而不是找到第一個(gè)匹配的內(nèi)容就結(jié)束。
-
i:不區(qū)分大小寫,表示在查找匹配時(shí)忽略pattern和字符串的大小寫。
-
m:多行模式,表示查找到一行文本末尾時(shí)會繼續(xù)查找。
-
y:粘附模式,表示只查找從1astIndex開始及之后的字符串。
-
u:Unicode模式,啟用Unicode匹配。
-
s:dotA11模式,表示元字符,匹配任何字符(包括\n或\r)。
5.2.1 RegExp實(shí)例屬性
每個(gè)RegExp實(shí)例都有下列屬性,提供有關(guān)模式的各方面信息。
+ global:布爾值,表示是否設(shè)置了g標(biāo)記。
+ ignoreCase:布爾值,表示是否設(shè)置了1標(biāo)記。
+ unicode:布爾值,表示是否設(shè)置了u標(biāo)記。
+ sticky:布爾值,表示是否設(shè)置了y標(biāo)記
+ astIndex:整數(shù),表示在源字符串中下一次搜索的開始位置,始終從0開始。
+ multiline:布爾值,表示是否設(shè)置了m標(biāo)記。
+ dotA11:布爾值,表示是否設(shè)置了。標(biāo)記。
+ source:正則表達(dá)式的字面量字符串(不是傳給構(gòu)造函數(shù)的模式字符串),沒有開頭和結(jié)尾的斜杠。
+ f1ags:正則表達(dá)式的標(biāo)記字符串。始終以字面量而非傳入構(gòu)造函數(shù)的字符串模式形式返回(沒5有前后斜杠)。
通過這些屬性可以全面了解正則表達(dá)式的信息,不過實(shí)際開發(fā)中用得并不多,因?yàn)槟J铰暶髦邪@些信息。
5.2.2 實(shí)例方法
1)exex()
Regexp實(shí)例的主要方法是 exec() ,主要用于配合捕獲組使用。
這個(gè)方法只接收一個(gè)參數(shù),即要應(yīng)用模式的字符串。如果找到了匹配項(xiàng),則返回包含第一不匹配信息的數(shù)組;如果沒找到匹配項(xiàng),則返回null。
返回的數(shù)組雖然是Array的實(shí)例,但包含兩個(gè)額外的屬性:index和input。index是字符串中匹配模式的起始位置,input是要查找的字符串。這個(gè)數(shù)組的第一個(gè)元素是匹配整個(gè)模式的字符串,其他元素是與表達(dá)式中的捕獲組匹配的字符串。如果模式中沒有捕獲組,則數(shù)組只包含一個(gè)元素。
這里不再繼續(xù)討論 exec() 方法的使用,可以自行百度詳細(xì)用法?;蛘哌@里我搜了兩篇說的還不錯(cuò)的文章:
https://blog.csdn.net/qq_35087256/article/details/79966865 | https://segmentfault.com/a/1190000018864720
2)test()
正則表達(dá)式的另一個(gè)方法是 test(),接收一個(gè)字符串參數(shù)。如果輸入的文本與模式匹配,則參數(shù)返回true,否則返回false。
這個(gè)方法適用于只想測試模式是否匹配,而不需要實(shí)際匹配內(nèi)容的情況。test() 經(jīng)常用在if語句中:
let text ="000-00-0000°; let pattern/\d{3}-\d{2}-\d{4}/; if (pattern.test(text))console.log ("The pattern was matched.");在這個(gè)例子中,正達(dá)式用于測試特定的數(shù)值序列。如果輸入的文本與模式匹配,則顯示匹配成功的消息。這個(gè)用法常用于驗(yàn)證用戶輸入,此時(shí)我們只在乎輸入是否有效,不關(guān)心為什么無效。
無論正則表達(dá)式是怎么創(chuàng)建的,繼承的方法 toLocaleString() 和 toString()都返回正則表達(dá)式的字面量表示。
注意:正則表達(dá)式的 valueOf()方法返回正則表達(dá)式本身。
5.2.3 RegExp構(gòu)造函數(shù)屬性
這里不進(jìn)行討論。
注意:RegExp構(gòu)造函數(shù)的所有屬性都沒有任何Web標(biāo)準(zhǔn)出處,因此不要在生成環(huán)境中使用它們。
5.3 原始值包裝類型
為了方便操作原始值,ECMAScript提供了3種特殊的引用類型:Boolean、Number和String。
這些類型具有本章介紹的其他引用類型一樣的特點(diǎn),但也具有與各自原始類型對應(yīng)的特殊行為。每當(dāng)用到某個(gè)原始值的方法或?qū)傩詴r(shí),后臺都會創(chuàng)建一個(gè)相應(yīng)原始包裝類型的對象,從而暴露出操作原始值的各種方法。來看下面的例子:
let sl = "some text"; let s2 = sl.substring(2);在這里,s1是一個(gè)包含字符串的變量,它是一個(gè)原始值。第二行緊接著在s1上調(diào)用了substring()方法,并把結(jié)果保存在s2中。我們知道,原始值本身不是對象,因此邏輯上不應(yīng)該有方法。而實(shí)際上這個(gè)例子又確實(shí)按照預(yù)期運(yùn)行了。這是因?yàn)楹笈_進(jìn)行了很多處理,從而實(shí)現(xiàn)了上述操作。具體來說,當(dāng)?shù)诙性L問s1時(shí),是以讀模式訪問的,也就是要從內(nèi)存中讀取變量保存的值。
在以讀模式訪問字符串值的任何時(shí)候,后臺都會執(zhí)行以下3步:
創(chuàng)建一個(gè)string類型的實(shí)例;
調(diào)用實(shí)例上的特定方法;
銷毀實(shí)例。
可以把這3步想象成執(zhí)行了如下3行ECMAScript代碼:
let s1 = new String("some text"); let s2 = s1.substring(2); s1 = null;這種行為可以讓原始值擁有有對象的行為,對布爾值和數(shù)值而言,以上3步也會在后臺發(fā)生,只不過使用的是Boolean和Number包裝類型而已。
引用類型與原始值包裝類型的主要區(qū)別在于對象的生命周期,在通過new實(shí)例化引用類型后,得到的實(shí)例會在離開作用域時(shí)被銷毀,而自動創(chuàng)建的原始值包裝對象則只存在于訪同它的那行代碼執(zhí)行期間。
這意味著不能在運(yùn)行時(shí)給原始值添加屬性和方法。比如下面的倒子:
可以顯式地使用Boolean、Number和string構(gòu)造函數(shù)創(chuàng)建原始值包裝對象。不過應(yīng)該在確實(shí)必要時(shí)再這么做,否則容易讓開發(fā)者疑惑,分不清它們到底是原始值還是引用值。在原始值包裝類型的實(shí)例上調(diào)用 typeof 會返回object,所有原始值包裝對象都會轉(zhuǎn)換為布爾值true。
另外,Object 構(gòu)透函數(shù)作為一個(gè)工廠方法,能夠根據(jù)傳入值的類型返回相應(yīng)原始值包裝類型的實(shí)例。比如:
let obj = new Object ("sometext"); console.log(obj intanceof string); //-> true //如果傳給Object的是字符串,則會創(chuàng)建一個(gè)String的實(shí)例。如果是數(shù)值,則會創(chuàng)建Number的實(shí)例。布爾值則會得到Boolean的實(shí)例。注意,使用new調(diào)用原始值包裝類型的構(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"雖然不推薦顯式創(chuàng)建原始值包裝類型的實(shí)例,但它們對于操作原始值的功能是很重要的。每個(gè)原值包裝類型都有相應(yīng)的一套方法來方便數(shù)據(jù)操作。
5.3.1 Boolean
Boolean是對應(yīng)布爾值的引用類型。要創(chuàng)建一個(gè)Boolean對象,就使用Boolean構(gòu)造函數(shù)并傳true或false,如下例所示:
let booleanobject = new Boolean(true);
Boolean 的實(shí)例會重寫 valueOf()方法,返回一個(gè)原始值true 或 false。toString()方法被調(diào)用時(shí)也會被覆蓋,返回字符串"true"或"false"。不過,Boolean對象在ECMAScript中用得很少。不僅如此,它們還容易引起誤會,尤其是在布爾表達(dá)式中使用Boolean對象時(shí)。
除此之外,原始值和引用值(Boolean對象)還有幾個(gè)區(qū)別。首先,typeof操作符對原始值返回“boolean”,但對引用值返回“object”。同樣,Boolean對象是 Boolean 類型的實(shí)例,在使用 instanceof 操作符時(shí)返回true,但對原始值則返回false,如下所示:
console.log(typeof falseObject); //-> object console.log(typeof falseValue); //-> boolean console.log(falseObject instanceof Boolean); //-> true console.log(falseValue instanceof Boolean): //-> false理解原始布爾值和Boolean對象之間的區(qū)別非常重要,強(qiáng)烈建議永遠(yuǎn)不要使用后者。
5.3.2 Number `
Number是對應(yīng)數(shù)值的引用類型。要創(chuàng)建一個(gè)Number對象,就使用Number構(gòu)造函數(shù)并傳入一個(gè)數(shù)值,如下例所示:
let NumberObject = new Number(10);
1)繼承的方法:
與Boolean 類型一樣,Number 類型重寫了 valueOf() 、totocalestring() 和toString() 方法。
valueOf()方法返回Number對象表示的原始數(shù)值,另外兩個(gè)方法返回?cái)?shù)值字符串。
toString() 方法可選地接收一個(gè)表示基數(shù)的參數(shù),并返回相應(yīng)基數(shù)形式的數(shù)值字符串。
2)將數(shù)值格式化為字符串的方法:
toFixed() 方法返回包含指定小數(shù)點(diǎn)位數(shù)的數(shù)值字符串,如:
let num = 10; console.log(num.toFixed(2)); //-> "10.00"如果數(shù)值本身的小數(shù)位超過了參數(shù)指定的位數(shù),則四舍五入到最接近的小數(shù)位。這個(gè)特點(diǎn)可以用于處理貨幣。但是要注意,多個(gè)浮點(diǎn)數(shù)值的數(shù)學(xué)計(jì)算不一定得到精確的結(jié)果。
注意:toFixed()方法可以表示有0-20個(gè)小數(shù)位的數(shù)值。某些瀏覽器可能支持更大的范圍,但這是通常被支持的范圍。
toExponential(),返回以科學(xué)記數(shù)法(也稱為指數(shù)記數(shù)法)表示的數(shù)值字符串。與toFixed()一樣,該方法也接收一個(gè)參數(shù),表示結(jié)果中小數(shù)的位。
toPrecision()方法會給根據(jù)情況返回最合理的驗(yàn)出結(jié)果。可能是固定長度,也可能是科學(xué)記數(shù)形式。這個(gè)方法接收一個(gè)參數(shù),表示結(jié)果中數(shù)字的總位數(shù)(不包含指數(shù))。來看幾個(gè)例子:
let num = 99; console.log(num.toprecision(1)); //-> "1e+2" console.log(num.toPrecision(2)); //-> "99" console.log(num.toPrecision(3)); //-> "99.0"在這個(gè)例子中,首先要用1位數(shù)字表示數(shù)值99,得到“1e+2”,也就是100。因?yàn)?9不能只用1數(shù)字來精確表示,所以這個(gè)方法就將它舍入為100,這樣就可以只用1位數(shù)字(及其科學(xué)記數(shù)法形式)來表示了。
用2位數(shù)字表示99得到“99”,用3位數(shù)字則是“99.0”。本質(zhì)上,toPrecision() 方法根據(jù)數(shù)值和精度來決定調(diào)用toFixed()還是toExponentia1()。為了以正確的小數(shù)位精確表示數(shù)值,這3個(gè)方法都會向上或向下s舍入。
注意 toprecisionl()方法可以表示帶1-21個(gè)小數(shù)位的數(shù)值。某些瀏覽器可能支持更大的范圍,但這是通常被支持的范圍。
3)isInteger() 方法與安全整數(shù) *
ES6新增了 Number.isInteger() 方法,用于辨別一個(gè)數(shù)值是否保存為整數(shù)。
IEEE 754數(shù)值格式有一個(gè)特殊的數(shù)值范圍,在這個(gè)范圍內(nèi)二進(jìn)制值可以表示一個(gè)整數(shù)值。這個(gè)數(shù)值范圍從Number.MIN_SAFE_INTEGER (-2^53+1) 到 Number.MAX_SAFE_INTEGER (2^53-1)。對超出這個(gè)范圍的數(shù)值,即使嘗試保存為整數(shù),IEEE754 編碼格式也意味著二進(jìn)制值可能會表示一個(gè)完全不同的數(shù)值。為了鑒別整數(shù)是否在這個(gè)范圍內(nèi),可以使用 Number.isSafeInteger()方法:
console.log(Number.isSafeInteger(-1 * (2 ** 53))); //-> false console.log(Number.isSafeInteger(-1 * (2 ** 53) + 1)); //-> true console.log(Number.isSafeInteger(2 ** 53)); //-> false console.log(Number.isSafeInteger((2 ** 53) - 1)); //-> true5.3.3 String `
String 是對應(yīng)字符串的引用類型。要創(chuàng)建一個(gè)String對象,使用String構(gòu)造函數(shù)并傳入一個(gè)數(shù)值,如下例所示:
let stringobject = new String(hello wor1d");
String對象的方法可以在所有字符串原始值上調(diào)用。3個(gè)繼承的方法 valueOf()、toLocaleString()和toString()都返回對象的原始字符串值。每個(gè)String對象都有一個(gè)1ength屬性,表示字符串中字符的數(shù)量。
1. JavaScript字符
1)16位碼元字符
JavaScript字符串由16位碼元(code unit)組成。對多數(shù)字符來說,每16位碼元對應(yīng)一個(gè)字符。換句話說,字符串的 1ength屬性表示字符串包含多少16位碼元;
let message ="abcde"; console.log(message.length); //-> 5charAt () 方法返回給定索引位置的字符,由傳給方法的整數(shù)參數(shù)指定。具體來說,這個(gè)方法查找指定索引位置的16位碼元,并返回該碼元對應(yīng)的字符。
charCodeAt()為法可以查看指定碼元的字將編碼碼,這個(gè)方法返回指定索引位置的碼元值,索引以整數(shù)指定:
let message = 'abcde'; // Unicode "Latin small letter C" 的編碼是 U+0063 console.log(message.charCodeAt(2)); //-> 99//十進(jìn)制 99 等于十六進(jìn)制 63 console.log(99 === 0x63); //-> truefromcharCode()方法用于根據(jù)價(jià)定的UTF-16碼元創(chuàng)建字符串中的字符。這個(gè)方法可以接受任意多個(gè)數(shù)值,并返回將所有數(shù)值對應(yīng)的字符拼接起來的字符申:
//Unicode "Latin small letter a" 的編碼是 U+0061 //Unicode "Latin small letter b" 的編碼是 U+0062 //Unicode "Latin small letter C" 的編碼是 U+0063 //Unicode "Latin small letter d" 的編碼是 U+0064 console.log(String.fromCharCode(0x61,0x62,0x63,0x64)); //-> abcd//0x0061 === 97 //0x0062 === 98 //0x0063 === 99 //0x0064 === 100 console.log (String.fromCharCode(97,98,99,100); //-> abcdJavaScript字符串使用了兩種Unicode編碼混合的策略:UCS-2和UTF-16。對于可以采用16位編碼的字符(U+0000 ~ U+FFFF),這兩種編碼實(shí)際上是一樣的。
2)代理對
對于U+0000-U+FFFF范圍內(nèi)的字符,length、 charAt()、charCodeAt()和 fromCharCode() 返回的結(jié)果都跟預(yù)期是一樣的。這是因?yàn)樵谶@個(gè)范圍內(nèi),每個(gè)字符都是用16位表示的,而這幾個(gè)方法也都基于16位碼元完成操作。只要字符編碼大小與碼元大小一一對應(yīng),這些方法就能如期工作。
這個(gè)對應(yīng)關(guān)系在擴(kuò)展到 Unicode增補(bǔ)字符平面時(shí)就不成立了。問題很簡單,即16位只能唯一表示65536個(gè)字符。這對于大多數(shù)語言字符集是足夠了,在 Unicode中稱為基本多語言平面(BMP)。為了表示更多的字符,Unicode采用了一個(gè)策略,即每個(gè)字符使用另外16位去選擇一個(gè)增補(bǔ)平面。
這種每字符使用兩個(gè)16位碼元的策略稱為代理對。
在涉及增補(bǔ)平面的字符時(shí),前面討論的字符串方法就會出問題。比如,下面的例子中使用了一個(gè)笑臉表情符號,也就是一個(gè)使用代理對編碼的字符:
//"smiling face with smiling eyes"表情符號的編碼是 U+1F60A //0x1F60A === 128522 let message="ab?de"; console.log(message.length); //-> 6 console.log(message.charAt(1)); //-> b console.log(message.charAt(2)); //-> <?> console.log(message.charAt(3)); //-> <?> console.log(message.charAt(4)); //-> dconsole.log(message.charCodeAt(1)); //-> 98 console.log(message.charCodeAt(2)); //-> 55357 console.log(message.charCodeAt(3)); //-> 56842 console.log(message.charCodeAt(4)); //-> 100console.log(String.fromCodePoint(0x1F60A)); //-> ?console.log(String.fromCharCode(97,98,55357,56842,100,101)); //-> ab?de這些方法仍然將16位碼元當(dāng)作一個(gè)字符,事實(shí)上索引2和索引3對應(yīng)的碼元應(yīng)該被看成一個(gè)代理對,只對應(yīng)一個(gè)字符。fromCharCode()方法仍然返回正確的結(jié)果,因?yàn)樗鼘?shí)際上是基于提供的二進(jìn)制表示直接組合成字符串。瀏覽器可以正確解析代理對(由兩個(gè)碼元構(gòu)成),并正確地將其識別為一個(gè)Unicode笑臉字符。
為正確解析既包含單碼元字符又包含代理對字符的字符串,可以使用 codePointAt() 來代替 charCodeAt() 。跟使用charCodeAt()時(shí)類似,codePointAt() 接收16位碼元的索引并返回該索引位置上的碼點(diǎn)(code point)。碼點(diǎn)是Unicode中一個(gè)字符的完整標(biāo)識。比如,“ c ”的碼點(diǎn)是0x0063,而“ ? ”的碼點(diǎn)是0x1F60A。碼點(diǎn)可能是16位,也可能是32位,而 codePointAt()方法可以從指定碼元位置識別完整的碼點(diǎn)。
let message = "ab?de"; console.log(message.codePointAt(1)); //-> 98 console.log(message.codePointAt(2)); //-> 128522 console.log(measage.codePointAt(3)); //-> 56842 console.log(message.codePointAt(4)); //-> 100注意,如果傳入的碼元索引并非代理對的開頭,就會返回錯(cuò)誤的碼點(diǎn)。這種錯(cuò)誤只有檢測單個(gè)字的時(shí)候才會出現(xiàn),可以通過從左到右按正確的碼元數(shù)遍歷字符串來規(guī)避。迭代字符串可以智能地識別理對的碼點(diǎn):
console.log([..."ab?de"]); //-> ["a","b","?","d","e"]fromCharCode()也有一個(gè)對應(yīng)的 fromcodePoint()。 這個(gè)方法接收任意數(shù)量的碼點(diǎn),返回對應(yīng)字符拼接起來的字符串:
console.log(String.fromCharCode(97,98,55357,56842,100,101)); //-> ab?de console.log(String.fromCodePoint(97,98,128522,100,101)); //-> ab?de2. normalize()方法
某些 Unicode字符可以有多種編碼方式。有的字符既可以通過一個(gè)BMP字符表示,也可以通過代理對表示。
該方法主要是為字符串應(yīng)用四種規(guī)范化形式:NFD、NFC,NFKD和NFKC。至于這四種形式具體含義和該方法的使用,因?yàn)閼?yīng)用情況的罕見這里不作總結(jié)??梢宰孕邪俣攘私狻?/p>
3. 字符串操作方法
concat() 用于將一個(gè)或多個(gè)字符串拼接成一個(gè)新字符串。
slice()、substr()、subString() 用于從字符串中提取子字符串。
4. 字符串位置方法
indexOf() 和 lastIndexOf() 用于在字符串中定位子字符串。
5. 字符串包含方法 *
ES6新增了3個(gè)用于判斷字符串中是否包含另一個(gè)字符串的方法:startsWith() 、 endWith() 和 includes()。
6. trim()方法
ECMAScript在所有字符串上都提供了 trim() 方法。這個(gè)方法會創(chuàng)建字符串的一個(gè)副本,刪除前、后所有空格符,再返回結(jié)果。原始字符串不會受影響。
trimLeft() 和 trimRight() 方法分別用于從字符串開始和結(jié)尾清理空格符。
7. repeat()方法
ECMAScript在所有字符串上都提供了 repeat() 方法。這個(gè)方法接收一個(gè)整數(shù)參數(shù),表示要將字符串復(fù)制多少次,然后返回拼接所有副本后的結(jié)果。
8. padStart() 和 padEnd() 方法
padStart() 和 padEnd() 方法會復(fù)制字符串,如果小于指定長度,則在相應(yīng)一邊填充字符,直至滿足長度條件。這兩個(gè)方法的第一個(gè)參數(shù)是長度,第二個(gè)參數(shù)是可選的填充字符串,默認(rèn)為空格(U+0020)。
9. 字符串迭代與解構(gòu)
字符中的原型上暴露了一個(gè)@@iterator方法,表示可以迭代字符串的每個(gè)字符??梢韵裣旅孢@樣手動使用迭代器:
let message = "abc"; let stringIterator = message[Symbol.iterator]();console.log(stringIterator.next()); //-> (value:"a", done:false) console.log(stringIterator.next()); //-> (value:"b", done:false) console.log(stringIterator.next()); //-> (value:"c", done:false) console.log(stringIterator.next()); //-> (value: undefined, done: true)在for-of循環(huán)中可以通過這個(gè)迭代器按序訪問每個(gè)字符:
for (const c of "abcde"){console.log(c); }//-> a //-> b //-> c //-> d //-> e有了這個(gè)迭代器之后,字符串就可以通過解構(gòu)操作符來解構(gòu)了。比如,可以更方便地把字符串分割為字符數(shù)組:
let message = "abcde"; console.log([...message]); //-> ["a","b","c","d","e"]10.字符串大小寫轉(zhuǎn)換
下一組方法涉及大小寫轉(zhuǎn)換,包括4個(gè)方法:toLowerCase()、tolocaleLowerCase() 、toUpperCase() 和 toLocaleCase()。
11. 字符串模式匹配方法
匹配字符串:match() 。本質(zhì)上與RegExp對象的 exec() 方法相同。
查找字符串:search() 。
替換字符串:replace() 。
拆分字符串:split() 。
12. localeCompare() 方法
5.4 單例內(nèi)置對象
ECMA-262對內(nèi)置對象的定義是“任何由ECMAScript實(shí)現(xiàn)提供、與宿主環(huán)境無關(guān),并在ECMAScript程序開始執(zhí)行時(shí)就存在的對象”。這就意味著,開發(fā)者不用顯式地實(shí)例化內(nèi)置對象,因?yàn)樗鼈円呀?jīng)實(shí)例化好了。前面我們已經(jīng)接觸了大部分內(nèi)置對象,包括Object、Array和String。本節(jié)介紹 ECMA-262定義的另外兩個(gè)單例內(nèi)置對象:G1obal和Math。
5.4.1 Global
G1obal對象是ECMAScript中最特別的對象,因?yàn)榇a不會顯式地訪問它。ECMA-262規(guī)定G1obal對象為一種兜底對象,它所針對的是不屬于任何對象的屬性和方法。
事實(shí)上,不存在全局變量或全局函數(shù)這種東西。在全局作用域中定義的變量和函數(shù)都會變成G1obal對象的屬性。
本書前面介紹的函數(shù),包括 isNaN()、isFinite()、parseInt()和 parseFloat(),實(shí)際上都是G1obal對象的方法。除了這些,G1obal對象上還有另外一些方法。
1. URL編碼方法
encodeURI()和 encodeURIComponent()方法用于編碼統(tǒng)一資源標(biāo)識符(URI),以便傳給瀏覽器。有效的URI不能包含某些字符,比如空格。使用URI編碼方法來編碼URI可以讓瀏覽器能夠理解它們,同時(shí)又以特殊的UTF-8編碼替換掉所有無效字符。
ecnodeURI()方法用于對整個(gè)URI進(jìn)行編碼,比如 “www.wrox.com/illegal value.js”。而encodeURIComponent()方法用于編碼URI中單獨(dú)的組件,比如前面URL中的 “i11egal value.js”。
2. eval() 方法
這個(gè)方法可能是整個(gè)ECMAScript語言中最強(qiáng)大的了。這個(gè)方法就是一個(gè)完整的ECMAScript解釋器,它接收一個(gè)參數(shù),即一個(gè)要執(zhí)行的ECMAScript字符串:
eval("alert('hello')""); //等價(jià)于下面的語句 alert("hello");當(dāng)解釋器發(fā)現(xiàn) eval() 調(diào)用時(shí),會將參數(shù)解釋為實(shí)際的ES語句,然后將其插入到該位置。通過 eval() 執(zhí)行的代碼屬于該調(diào)用所在的上下文,被執(zhí)行的代碼與該上下文擁有相同的作用域鏈。這意味著定義在包含上下文中的變量可以在 eval() 調(diào)用內(nèi)部被引用,比如下面這個(gè)例子:
let msg = "hello world"; eval("console.log(msg)"); //-> "hello world"通過 eval() 定義的任何變量和函數(shù)都不會被提升,這是因?yàn)樵诮馕龃a的時(shí)候,它們是被包含在一個(gè)字符串中的。它們只是在 eval() 執(zhí)行的時(shí)候才會被創(chuàng)建。
在嚴(yán)格模式下,在 eval() 內(nèi)部創(chuàng)建的變量和函數(shù)無法被外部訪問。
注意:解釋代碼字符串的能力是非常強(qiáng)大的,但也非常危險(xiǎn)。在使用 eval()的時(shí)候必須極為慎重,特別是在解釋用戶輸入的內(nèi)容時(shí)。因?yàn)檫@個(gè)方法會對XSS利用暴露出很大的攻擊面。惡意用戶可能插入會導(dǎo)致你網(wǎng)站或應(yīng)用崩潰的代碼。
3. Global對象屬性
這里不再列出。
4. window對象
雖然ECMA-262沒有規(guī)定直接訪問Global對象的方式,但瀏覽器將window對象實(shí)現(xiàn)為Global對象的代理。因此,所有全局作用域中聲明的變量和函數(shù)都變成了window的屬性。
window對象會在第12章更加詳細(xì)的介紹。
5.4.2 Math
這里不再介紹。
總結(jié)
以上是生活随笔為你收集整理的《JavaScript高级程序设计(第四版)》红宝书学习笔记(第五章:基本引用类型,原始值包装类型,单例内置对象)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数学之路(3)-机器学习(3)-机器学习
- 下一篇: JavaScript基础三