js紅寶書筆記四 第五章 原始值包裝類型 單例內(nèi)置對象

本文繼續(xù)對JavaScript高級程序設(shè)計第四版 第五章 基本引用類型 進行學習

一打洼、5.1節(jié) Date
二、5.2節(jié) RegExp
三玩焰、5.3節(jié) 原始值包裝類型

為了方便操作原始值由驹,ECMAScript 提供了 3 種特殊的引用類型:Boolean、Number 和 String昔园。

這些類型具有本章介紹的其他引用類型一樣的特點蔓榄,但也具有與各自原始類型對應的特殊行為。每當用到某個原始值的方法或?qū)傩詴r默刚,后臺都會創(chuàng)建一個相應原始包裝類型的對象甥郑,從而暴露出操作原始值的各種方法。來看下面的例子:

let s1 = "some text";
let s2 = s1.substring(2);

在這里荤西,s1 是一個包含字符串的變量澜搅,它是一個原始值伍俘。第二行緊接著在 s1 上調(diào)用了 substring()方法,并把結(jié)果保存在 s2 中勉躺。我們知道癌瘾,原始值本身不是對象,因此邏輯上不應該有方法饵溅。而實際上這個例子又確實按照預期運行了妨退。這是因為后臺進行了很多處理,從而實現(xiàn)了上述操作蜕企。具體來說咬荷,當?shù)诙性L問 s1 時,是以讀模式訪問的轻掩,也就是要從內(nèi)存中讀取變量保存的值幸乒。在以讀模式訪問字符串值的任何時候,后臺都會執(zhí)行以下 3 步:

  • (1) 創(chuàng)建一個 String 類型的實例放典;
  • (2) 調(diào)用實例上的特定方法逝变;
  • (3) 銷毀實例。

可以把這 3 步想象成執(zhí)行了如下 3 行 ECMAScript 代碼:

let s1 = new String("some text");
let s2 = s1.substring(2);
s1 = null;

這種行為可以讓原始值擁有對象的行為奋构。對布爾值和數(shù)值而言壳影,以上 3 步也會在后臺發(fā)生,只不過使用的是 Boolean 和 Number 包裝類型而已弥臼。

1.引用類型與原始值包裝類型的主要區(qū)別在于對象的生命周期

在通過 new 實例化引用類型后宴咧,得到的實例會在離開作用域時被銷毀,而自動創(chuàng)建的原始值包裝對象則只存在于訪問它的那行代碼執(zhí)行期間径缅。這意味著不能在運行時給原始值添加屬性和方法掺栅。比如下面的例子:

let s1 = "some text";
s1.color = "red";
console.log(s1.color); // undefined

這里的第二行代碼嘗試給字符串 s1 添加了一個 color 屬性∧芍恚可是氧卧,第三行代碼訪問 color 屬性時,它卻不見了氏堤。原因就是第二行代碼運行時會臨時創(chuàng)建一個 String 對象沙绝,而當?shù)谌写a執(zhí)行時窄锅,這個對象已經(jīng)被銷毀了箱亿。實際上蝌矛,第三行代碼在這里創(chuàng)建了自己的 String 對象牵触,但這個對象沒有 color 屬性丙曙。

2.顯式創(chuàng)建原始值包裝對象

可以顯式地使用 Boolean赖晶、Number 和 String 構(gòu)造函數(shù)創(chuàng)建原始值包裝對象巾兆。不過應該在確實必要時再這么做如捅,否則容易讓開發(fā)者疑惑同欠,分不清它們到底是原始值還是引用值样傍。在原始值包裝類型的實例上調(diào)用 typeof 會返回"object"横缔,所有原始值包裝對象都會轉(zhuǎn)換為布爾值 true。

另外铭乾,Object 構(gòu)造函數(shù)作為一個工廠方法剪廉,能夠根據(jù)傳入值的類型返回相應原始值包裝類型的實例。比如:

let obj = new Object("some text");
console.log(obj instanceof String); // true

如果傳給 Object 的是字符串炕檩,則會創(chuàng)建一個 String 的實例斗蒋。如果是數(shù)值,則會創(chuàng)建 Number 的實例笛质。布爾值則會得到 Boolean 的實例泉沾。

注意,使用 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"

在這個例子中,變量 number 中保存的是一個值為 25 的原始數(shù)值敲霍,而變量 obj 中保存的是一個Number 的實例俊马。

雖然不推薦顯式創(chuàng)建原始值包裝類型的實例,但它們對于操作原始值的功能是很重要的肩杈。每個原始值包裝類型都有相應的一套方法來方便數(shù)據(jù)操作柴我。

四、Boolean

Boolean 是對應布爾值的引用類型扩然。要創(chuàng)建一個 Boolean 對象艘儒,就使用 Boolean 構(gòu)造函數(shù)并傳入true 或 false,如下例所示:

let booleanObject = new Boolean(true); 

Boolean 對象在 ECMAScript 中用得很少夫偶。不僅如此界睁,它們還容易引起誤會,尤其是在布爾表達式中使用 Boolean 對象時兵拢,比如:

let falseObject = new Boolean(false);
let result = falseObject && true;
console.log(result); // true
let falseValue = false;
result = falseValue && true;
console.log(result); // false

在這段代碼中翻斟,我們創(chuàng)建一個值為 false 的 Boolean 對象。然后说铃,在一個布爾表達式中通過&&操作將這個對象與一個原始值 true 組合起來杨赤。在布爾算術(shù)中,false && true 等于 false截汪。可是植捎,這個表達式是對 falseObject 對象而不是對它表示的值(false)求值衙解。前面剛剛說過,所有對象在布爾表達式中都會自動轉(zhuǎn)換為 true焰枢,因此 falseObject 在這個表達式里實際上表示一個 true 值蚓峦。那么true && true 當然是 true舌剂。

理解原始布爾值和 Boolean 對象之間的區(qū)別非常重要,強烈建議永遠不要使用后者暑椰。

五霍转、Number

Number 是對應數(shù)值的引用類型。要創(chuàng)建一個 Number 對象一汽,就使用 Number 構(gòu)造函數(shù)并傳入一個數(shù)值避消,如下例所示:

let numberObject = new Number(10);

與 Boolean 類型一樣,Number 類型重寫了 valueOf()召夹、toLocaleString()和 toString()方法岩喷。valueOf()方法返回 Number 對象表示的原始數(shù)值,另外兩個方法返回數(shù)值字符串监憎。toString()方法可選地接收一個表示基數(shù)的參數(shù)纱意,并返回相應基數(shù)形式的數(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 類型還提供了幾個用于將數(shù)值格式化為字符串的方法偷霉。

1.toFixed()自動舍入
let num = 10.005;
console.log(num.toFixed(2)); // "10.01"
2.toExponential()

返回以科學記數(shù)法(也稱為指數(shù)記數(shù)法)表示的數(shù)值字符串。與 toFixed()一樣褐筛,toExponential()也接收一個參數(shù)类少,表示結(jié)果中小數(shù)的位數(shù)。來看下面的例子:

let num = 10;
console.log(num.toExponential(1)); // "1.0e+1"

這段代碼的輸出為"1.0e+1"死讹。一般來說瞒滴,這么小的數(shù)不用表示為科學記數(shù)法形式。如果想得到數(shù)值最適當?shù)男问皆蘧敲纯梢允褂?toPrecision()妓忍。toPrecision()方法會根據(jù)情況返回最合理的輸出結(jié)果,可能是固定長度愧旦,也可能是科學記數(shù)法形式世剖。這個方法接收一個參數(shù),表示結(jié)果中數(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" 

與 Boolean 對象類似旁瘫,Number 對象也為數(shù)值提供了重要能力。但是琼蚯,考慮到兩者存在同樣的潛在問題酬凳,因此并不建議直接實例化 Number 對象。

六遭庶、String

每個 String 對象都有一個 length 屬性宁仔,表示字符串中字符的數(shù)量。來看下面的例子:

let stringValue = "hello world";
console.log(stringValue.length); // "11"

這個例子輸出了字符串"hello world"中包含的字符數(shù)量:11峦睡。注意翎苫,即使字符串中包含雙字節(jié)字符(而不是單字節(jié)的 ASCII 字符)权埠,也仍然會按單字符來計數(shù)。

1.charAt charCodeAt fromCharCode
2.normalize

Unicode提供了 4種規(guī)范化形式煎谍,可以將類似上面的字符規(guī)范化為一致的格式攘蔽,無論底層字符的代碼是什么。這 4種規(guī)范化形式是:NFD(Normalization Form D)呐粘、NFC(Normalization Form C)满俗、NFKD(Normalization Form KD)和 NFKC(Normalization Form KC)∈驴蓿可以使用 normalize()方法對字符串應用上述規(guī)范化形式漫雷,使用時需要傳入表示哪種形式的字符串:"NFD"、"NFC"鳍咱、"NFKD"或"NFKC"降盹。

3.concat
4.slice()、substr()和 substring()
5.indexOf()和 lastIndexOf()
6.startsWith()谤辜、endsWith()和 includes()

ECMAScript 6 增加了 3 個用于判斷字符串中是否包含另一個字符串的方法蓄坏。它們的區(qū)別在于,startsWith()檢查開始于索引 0 的匹配項丑念,endsWith()檢查開始于索引(string.length - substring.length)的匹配項涡戳,而 includes()檢查整個字符串:

let message = "foobarbaz";
console.log(message.startsWith("foo")); // true
console.log(message.startsWith("bar")); // false
console.log(message.endsWith("baz")); // true
console.log(message.endsWith("bar")); // false
console.log(message.includes("bar")); // true
console.log(message.includes("qux")); // false

startsWith()和 includes()方法接收可選的第二個參數(shù),表示開始搜索的位置脯倚。如果傳入第二個參數(shù)渔彰,則意味著這兩個方法會從指定位置向著字符串末尾搜索,忽略該位置之前的所有字符推正。下面是一個例子:

let message = "foobarbaz";
console.log(message.startsWith("foo")); // true
console.log(message.startsWith("foo", 1)); // false
console.log(message.includes("bar")); // true
console.log(message.includes("bar", 4)); // false

endsWith()方法接收可選的第二個參數(shù)恍涂,表示應該當作字符串末尾的位置。如果不提供這個參數(shù)植榕,那么默認就是字符串長度再沧。如果提供這個參數(shù),那么就好像字符串只有那么多字符一樣:

let message = "foobarbaz";
console.log(message.endsWith("bar")); // false
console.log(message.endsWith("bar", 6)); // true 
7. trim()
8. repeat()
9. padStart()和 padEnd()

padStart()和 padEnd()方法會復制字符串尊残,如果小于指定長度炒瘸,則在相應一邊填充字符,直至滿足長度條件寝衫。這兩個方法的第一個參數(shù)是長度顷扩,第二個參數(shù)是可選的填充字符串,默認為空格(U+0020)慰毅。

let stringValue = "foo";
console.log(stringValue.padStart(6)); // " foo"
console.log(stringValue.padStart(9, ".")); // "......foo"
console.log(stringValue.padEnd(6)); // "foo "
console.log(stringValue.padEnd(9, ".")); // "foo......" 
10.字符串迭代與解構(gòu)

字符串的原型上暴露了一個@@iterator 方法屎即,表示可以迭代字符串的每個字符。可以像下面這樣手動使用迭代器:

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)中可以通過這個迭代器按序訪問每個字符:

for (const c of "abcde") {
 console.log(c);
}
// a
// b
// c
// d
// e

有了這個迭代器之后技俐,字符串就可以通過解構(gòu)操作符來解構(gòu)了。比如统台,可以更方便地把字符串分割為字符數(shù)組:

let message = "abcde";
console.log([...message]); // ["a", "b", "c", "d", "e"] 
11. 字符串大小寫轉(zhuǎn)換

下一組方法涉及大小寫轉(zhuǎn)換雕擂,包括 4 個方法:toLowerCase()、toLocaleLowerCase()贱勃、toUpperCase()和toLocaleUpperCase()井赌。toLowerCase()和toUpperCase()方法是原來就有的方法,與 java.lang.String 中的方法同名贵扰。toLocaleLowerCase()和 toLocaleUpperCase()方法旨在基于特定地區(qū)實現(xiàn)仇穗。在很多地區(qū),地區(qū)特定的方法與通用的方法是一樣的戚绕。但在少數(shù)語言中(如土耳其語)纹坐,Unicode 大小寫轉(zhuǎn)換需應用特殊規(guī)則,要使用地區(qū)特定的方法才能實現(xiàn)正確轉(zhuǎn)換舞丛。

12. 字符串模式匹配方法
  • match
  • search
  • replace
13.localeCompare()

localeCompare()的獨特之處在于耘子,實現(xiàn)所在的地區(qū)(國家和語言)決定了這個方法如何比較字符串。在美國球切,英語是 ECMAScript 實現(xiàn)的標準語言谷誓,localeCompare()區(qū)分大小寫,大寫字母排在小寫字母前面吨凑。但其他地區(qū)未必是這種情況捍歪。

七、單例內(nèi)置對象

ECMA-262 對內(nèi)置對象的定義是“任何由 ECMAScript 實現(xiàn)提供鸵钝、與宿主環(huán)境無關(guān)糙臼,并在 ECMAScript程序開始執(zhí)行時就存在的對象”。這就意味著蒋伦,開發(fā)者不用顯式地實例化內(nèi)置對象弓摘,因為它們已經(jīng)實例化好了。前面我們已經(jīng)接觸了大部分內(nèi)置對象痕届,包括 Object韧献、Array 和 String。本節(jié)介紹 ECMA-262定義的另外兩個單例內(nèi)置對象:Global 和 Math研叫。

1.Global

Global 對象是 ECMAScript 中最特別的對象锤窑,因為代碼不會顯式地訪問它。ECMA-262 規(guī)定 Global對象為一種兜底對象嚷炉,它所針對的是不屬于任何對象的屬性和方法渊啰。事實上,不存在全局變量或全局函數(shù)這種東西。在全局作用域中定義的變量和函數(shù)都會變成 Global 對象的屬性 绘证。本書前面介紹的函數(shù)隧膏,包括 isNaN()、isFinite()嚷那、parseInt()和 parseFloat()胞枕,實際上都是 Global 對象的方法。除了這些魏宽,Global 對象上還有另外一些方法腐泻。

  • encodeURI()和 encodeURIComponent()方法用于編碼統(tǒng)一資源標識符(URI),以便傳給瀏覽器队询。有效的 URI 不能包含某些字符派桩,比如空格。使用 URI 編碼方法來編碼 URI 可以讓瀏覽器能夠理解它們蚌斩,同時又以特殊的 UTF-8 編碼替換掉所有無效字符铆惑。
  • eval()方法。這個方法就是一個完整的 ECMAScript 解釋器凳寺,它接收一個參數(shù)鸭津,即一個要執(zhí)行的CMAScript(JavaScript)字符串。在使用 eval()的時候必須極為慎重肠缨,特別是在解釋用戶輸入的內(nèi)容時逆趋。因為這個方法會對 XSS 利用暴露出很大的攻擊面。惡意用戶可能插入會導致你網(wǎng)站或應用崩潰的代碼晒奕。
  • Global 對象有很多屬性闻书,其中一些前面已經(jīng)提到過了。像 undefined脑慧、NaN 和 Infinity 等特殊值都是 Global 對象的屬性魄眉。此外,所有原生引用類型構(gòu)造函數(shù)闷袒,比如 Object 和 Function坑律,也都是Global 對象的屬性。
  • 雖然 ECMA-262 沒有規(guī)定直接訪問 Global 對象的方式囊骤,但瀏覽器將 window 對象實現(xiàn)為 Global對象的代理晃择。因此,所有全局作用域中聲明的變量和函數(shù)都變成了 window 的屬性也物。來看下面的例子:
var color = "red";
function sayColor() {
 console.log(window.color);
}
window.sayColor(); // "red"

這里定義了一個名為color的全局變量和一個名為sayColor()的全局函數(shù)宫屠。在sayColor()內(nèi)部,通過 window.color 訪問了 color 變量滑蚯,說明全局變量變成了 window 的屬性浪蹂。接著抵栈,又通過 window對象直接調(diào)用了 window.sayColor()函數(shù),從而輸出字符串坤次。

2.Math
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末古劲,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子缰猴,更是在濱河造成了極大的恐慌绢慢,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件洛波,死亡現(xiàn)場離奇詭異,居然都是意外死亡骚露,警方通過查閱死者的電腦和手機蹬挤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棘幸,“玉大人焰扳,你說我怎么就攤上這事∥笮” “怎么了吨悍?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蹋嵌。 經(jīng)常有香客問我育瓜,道長,這世上最難降的妖魔是什么栽烂? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任躏仇,我火速辦了婚禮,結(jié)果婚禮上腺办,老公的妹妹穿的比我還像新娘焰手。我一直安慰自己,他們只是感情好怀喉,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布书妻。 她就那樣靜靜地躺著,像睡著了一般躬拢。 火紅的嫁衣襯著肌膚如雪躲履。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天估灿,我揣著相機與錄音崇呵,去河邊找鬼。 笑死馅袁,一個胖子當著我的面吹牛域慷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼犹褒,長吁一口氣:“原來是場噩夢啊……” “哼抵窒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起叠骑,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤李皇,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后宙枷,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掉房,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年慰丛,在試婚紗的時候發(fā)現(xiàn)自己被綠了卓囚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡诅病,死狀恐怖哪亿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情贤笆,我是刑警寧澤蝇棉,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站芥永,受9級特大地震影響篡殷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜恤左,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一贴唇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧飞袋,春花似錦戳气、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至纲仍,卻和暖如春呀袱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背郑叠。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工夜赵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乡革。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓寇僧,卻偏偏與公主長得像摊腋,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子嘁傀,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容