成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

掌握 Javascript 類型轉(zhuǎn)換:從規(guī)則開始

mikyou / 1372人閱讀

摘要:首先,為了掌握好類型轉(zhuǎn)換,我們要理解一個重要的抽象操作為什么說這是個抽象操作呢因為這是內(nèi)部才會使用的操作,我們不會顯示調(diào)用到?;疽?guī)則中的類型轉(zhuǎn)換總是返回基本類型值,如字符串?dāng)?shù)字和布爾值,不會返回對象和函數(shù)。

Javascript 里的類型轉(zhuǎn)換是一個你永遠(yuǎn)繞不開的話題,不管你是在面試中還是工作寫代碼,總會碰到這類問題和各種的坑,所以不學(xué)好這個那是不行滴。關(guān)于類型轉(zhuǎn)換我也看過不少的書和各種博客、帖子,也查過規(guī)范和做過各種測試,這里就談?wù)勎业目偨Y(jié)和理解吧。

首先,為了掌握好類型轉(zhuǎn)換,我們要理解一個重要的抽象操作:ToPrimitive

ToPrimitive

為什么說這是個抽象操作呢?因為這是 Javascript 內(nèi)部才會使用的操作,我們不會顯示調(diào)用到。當(dāng)需要將對象轉(zhuǎn)換為相應(yīng)的基本類型值時,ToPrimitive 就會調(diào)用對象的內(nèi)部方法 [[DefaultValue]] 來完成。

ToPrimitive 操作接收兩個參數(shù),一個是 input 需要轉(zhuǎn)換的值,第二個是可選參數(shù) hint 代表期望的轉(zhuǎn)換類型。并且在調(diào)用 [[DefaultValue]] 的時候 hint 會傳遞過去。

這里我們首先只需要知道 [[DefaultValue]] 會調(diào)用 valueOf()toString() 來完成基本類型值的轉(zhuǎn)換。但是請注意:valueOf()toString() 的調(diào)用邏輯順序并不是固定的取決于 hint 參數(shù),這個我們下面會講到。

基本規(guī)則

JavaScript 中的類型轉(zhuǎn)換總是返回基本類型值,如字符串、數(shù)字和布爾值,不會返回對象和函數(shù)。那么這也對應(yīng)了三種抽象操作:ToString、ToNumberToBoolean,下面就來逐一說明。

ToString
var a = {};
console.log(String(a));
// 顯式類型轉(zhuǎn)換,輸出為:"[object Object]"

以上代碼我們通常稱為顯示類型轉(zhuǎn)換,這里面就包含 ToString 抽象操作,也就是把非字符串值轉(zhuǎn)換為字符串的操作。

先來看看非對象的基本類型值的 ToString 轉(zhuǎn)換規(guī)則:

輸入類型 輸出結(jié)果
Undefined "undefined"
Null "null"
Boolean 輸入 true,輸出 "true"
輸入 false,輸出 "false"
Number 輸入 NaN,輸出 "NaN"
輸入 +0-0,輸出 "0"
如果輸入小于 0 的數(shù)字,如:-2,輸出將包括負(fù)號:"-2"
輸入 Infinity,輸出 "Infinity"

接著我們重點來看一下輸入是對象的轉(zhuǎn)換規(guī)則。

這個時候 ToPrimitive 就出場了,并且 hint 參數(shù)是 String。還記得 ToPrimitive 內(nèi)部是調(diào)用的[[DefaultValue]]嗎,并且這個時候 hint 是 String 。下面來看下這種情況下 ToPrimitive 的調(diào)用邏輯:

toPrimitive 調(diào)用 [[DefaultValue]] 并傳遞 hint,然后返回調(diào)用結(jié)果

[[DefaultValue]] 根據(jù) hint 是 String 執(zhí)行以下調(diào)用順序:

如果對象存在 toString() 并返回一個基本類型值,即返回這個值

如果 toString() 不存在或返回的不是一個基本類型值,就調(diào)用 valueOf()

如果 valueOf() 存在并返回一個基本類型值,即返回這個值

如果 valueOf() 不存在或返回的不是一個基本類型值,則拋出 TypeError 異常

那么這里就可以總結(jié)為:對象在類型轉(zhuǎn)換為字符串時, toString() 的調(diào)用順序在 valueOf() 之前,并且這兩個方法如果都沒有返回一個基本類型值,則拋出異常;如果返回了基本類型值 primValue,則返回 String(primValue)

基本類型值的 ToString 結(jié)果參看前面那個表格

我們來測試一下。先看下這節(jié)開頭的例子:

var a = {};
console.log(String(a));

字面量對象的原型是 Object.prototype,Object.prototype.toString() 返回內(nèi)部屬性 [[Class]] 的值,那么結(jié)果就是 [object Object]。OK 沒有問題

然后測試一下 ToPrimitive 的調(diào)用邏輯。來看下這段代碼:

var a = Object.create(null);

上面的意思是創(chuàng)建一個沒有原型的對象(沒有原型就沒有繼承的 toString()valueOf() 了)。接下來:

console.log(String(a));
// Uncaught TypeError: Cannot convert object to primitive value

這里因為沒有 toString()valueOf() 所以就拋出 TypeError 異常了。OK,跟前面的總結(jié)一致。

下面來測試一下 toString()valueOf() 的調(diào)用順序邏輯,上代碼:

a.toString = function() {
  return "hello";
};

a.valueOf = function() {
  return true;
};

console.log(String(a)); // "hello"

我們加入了 toString()valueOf() ,并且跟前面的總結(jié)一致,確實是 toString() 先返回結(jié)果。接著做一下變化:

a.toString = function() {
  return {};
};
// 或是直接去掉這個方法,a.toString = undefined;

a.valueOf = function() {
  return true;
};

console.log(String(a)); // "true"

當(dāng) toString() 返回的不是一個基本類型值或不存在 toString() 時,返回 valueOf() 的結(jié)果,并且遵循基本類型值的 ToString 轉(zhuǎn)換結(jié)果。OK,驗證沒有問題 其他的情況也可以根據(jù)前面的總結(jié)邏輯自己驗證下。

在《Javascript 高級程序設(shè)計(第 3 版)》和《你不知道的 Javascript(中卷)》上均未提到類型轉(zhuǎn)換到字符串會與 valueOf() 有關(guān)系
ToNumber

首先照例先來看下非對象的基本類型值的 ToNumber 轉(zhuǎn)換規(guī)則:

輸入類型 輸出結(jié)果
Undefined NaN
Null 0
Boolean 輸入 true,輸出 1
輸入 false,輸出 0
Number 輸入 "",輸出 0
輸入 "Infinity",輸出 Infinity
輸入有效數(shù)字的字符串(包括二、八和十六進(jìn)制),輸出數(shù)字的十進(jìn)制數(shù)值
如果輸入包含非數(shù)字格式的字符串,輸出 NaN
字符串轉(zhuǎn)數(shù)字上面只說了一些常用的情況,更多細(xì)節(jié)請看 這里

然后來看看對象 ToNumber 的情況。這里與對象轉(zhuǎn)字符串的情況類似,也會調(diào)用 ToPrimitive 來轉(zhuǎn)換(hint 是 Number)。但細(xì)節(jié)與 ToString 稍有不同,這里直接給出結(jié)論:

對象在類型轉(zhuǎn)換為數(shù)字時, valueOf() 的調(diào)用順序在 toString() 之前,并且這兩個方法如果都沒有返回一個基本類型值,則拋出異常;如果返回了基本類型值 primValue,則返回 Number(primValue)

這里驗證了 ToPrimitive 里面說到的,[[DefaultValue]] 會根據(jù) hint 參數(shù)決定 toString() 和 valueOf() 的調(diào)用順序

接著來用代碼說話:

var a = Object.create(null);
console.log(Number(a));
// Uncaught TypeError: Cannot convert object to primitive value

這里因為沒有 toString()valueOf() 所以就拋出 TypeError 異常了。OK,跟前面的總結(jié)一致。

我們先加入 valueOf() 方法:

a.valueOf = function() {
  return 123;
}
console.log(Number(a)); // 123

valueOf() 返回了數(shù)字 123,所以輸出沒問題。再修改一下:

a.valueOf = function() {
  return true;
}
console.log(Number(a)); // 1

valueOf() 返回了 true,這也是一個基本類型,然后根據(jù)基本類型轉(zhuǎn)換規(guī)則 true 轉(zhuǎn)換為 1,也是對的。

再來:

a.valueOf = function() {
  return NaN;
}
console.log(Number(a)); // NaN

NaN 是一個特殊的數(shù)值,所以也是基本類型。OK,也是對的。

這里的結(jié)果說明了《Javascript 高級程序設(shè)計(第 3 版)》關(guān)于對象轉(zhuǎn)換為數(shù)字的解釋是有錯誤的,書上是這么說的:如果轉(zhuǎn)換的結(jié)果是 NaN,則調(diào)用對象的 toString() 方法

再來驗證一下 toString() 的調(diào)用順序:

a.valueOf = function() {
  return {};
}
a.toString = function() {
  return "123";
}
console.log(Number(a)); // 123

因為 valueOf() 返回了對象非基本類型值,轉(zhuǎn)而執(zhí)行 toString(),返回的 "123" 根據(jù)字符串轉(zhuǎn)換數(shù)字的規(guī)則就是 123,對于 valueOf() 和 toString() 的執(zhí)行順序驗證也是 OK 的。

ToBoolean

最后我們來看看轉(zhuǎn)換為布爾值。這個比較簡單,一個列表可以全部歸納了:

輸入類型 輸出結(jié)果
Undefined false
Null false
Number 輸入 +0,-0,NaN,輸出 false
輸入其他數(shù)字,輸出 true
String 輸入 length 為 0 的字符串(如:""),輸出 false
輸入其他字符串,輸出 true
Object 輸入任何對象類型,輸出 true

ToBoolean 轉(zhuǎn)換規(guī)則比較簡單,只有一個需要注意的地方,那就是封箱操作:

var a = new Boolean(false);
console.log(Boolean(a));
// 輸出是 true 不是 false 喔

new Boolean(false) 返回的是對象不是布爾值,所以最好避免進(jìn)行類似的操作。

總結(jié)

以上即是我總結(jié)的 JS 類型轉(zhuǎn)換基本規(guī)則,當(dāng)你明顯感知類型轉(zhuǎn)換即將發(fā)生時可以拿上面的規(guī)則去套(也就是我們通常說的顯式類型轉(zhuǎn)換,以上轉(zhuǎn)換規(guī)則面試時特別有用喔)。

既然規(guī)則有了,下一篇準(zhǔn)備聊一下隱式類型轉(zhuǎn)換,有了這篇的基礎(chǔ)掌握隱式轉(zhuǎn)換會容易很多。

歡迎 star 和關(guān)注我的 JS 博客:小聲比比 Javascript

參考資料

ES5 規(guī)范注釋

《Javascript 高級程序設(shè)計(第 3 版)》

《你不知道的 Javascript(中卷)》

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/104474.html

相關(guān)文章

  • 掌握 Javascript 類型轉(zhuǎn)換:隱式轉(zhuǎn)換救救孩子

    摘要:看下面的代碼和會對操作數(shù)執(zhí)行條件判斷,如果操作數(shù)不是布爾值,會先執(zhí)行類型轉(zhuǎn)換后再執(zhí)行條件判斷。大家記住這個規(guī)則布爾值如果與其他類型進(jìn)行抽象比較,會先用將布爾值轉(zhuǎn)換為數(shù)字再比較。 在上一篇中我們聊過了 JS 類型轉(zhuǎn)換的規(guī)則和我發(fā)現(xiàn)的一些常見書籍中關(guān)于類型轉(zhuǎn)換的一些小錯誤,當(dāng)碰到顯示類型轉(zhuǎn)換的時候大家可以按照這些規(guī)則去拆解出答案。但 JS 中存在一些很隱晦的隱式類型轉(zhuǎn)換,這一篇就來談下我對...

    weapon 評論0 收藏0
  • 一名【合格】前端工程師的自檢清單

    摘要:在他的重學(xué)前端課程中提到到現(xiàn)在為止,前端工程師已經(jīng)成為研發(fā)體系中的重要崗位之一。大部分前端工程師的知識,其實都是來自于實踐和工作中零散的學(xué)習(xí)。一基礎(chǔ)前端工程師吃飯的家伙,深度廣度一樣都不能差。 開篇 前端開發(fā)是一個非常特殊的行業(yè),它的歷史實際上不是很長,但是知識之繁雜,技術(shù)迭代速度之快是其他技術(shù)所不能比擬的。 winter在他的《重學(xué)前端》課程中提到: 到現(xiàn)在為止,前端工程師已經(jīng)成為研...

    羅志環(huán) 評論0 收藏0
  • 一名【合格】前端工程師的自檢清單

    摘要:在他的重學(xué)前端課程中提到到現(xiàn)在為止,前端工程師已經(jīng)成為研發(fā)體系中的重要崗位之一。大部分前端工程師的知識,其實都是來自于實踐和工作中零散的學(xué)習(xí)。一基礎(chǔ)前端工程師吃飯的家伙,深度廣度一樣都不能差。開篇 前端開發(fā)是一個非常特殊的行業(yè),它的歷史實際上不是很長,但是知識之繁雜,技術(shù)迭代速度之快是其他技術(shù)所不能比擬的。 winter在他的《重學(xué)前端》課程中提到: 到現(xiàn)在為止,前端工程師已經(jīng)成為研發(fā)體系...

    isaced 評論0 收藏0
  • 前端基礎(chǔ)入門四(JavaScript基礎(chǔ))

    摘要:學(xué)習(xí)目標(biāo)掌握編程的基本思維掌握編程的基本語法我們先來學(xué)習(xí)基礎(chǔ),后續(xù)會講解高級。語句基本語法當(dāng)循環(huán)條件為時,執(zhí)行循環(huán)體,當(dāng)循環(huán)條件為時,結(jié)束循環(huán)。基礎(chǔ)語法循環(huán)體循環(huán)條件代碼示例初始化變量循環(huán)體自增循環(huán)條件語句和一般用來解決無法確認(rèn)次數(shù)的循環(huán)。 學(xué)習(xí)目標(biāo): 掌握編程的基本思維 掌握編程的基本語法 我們先來學(xué)習(xí)JavaScript基礎(chǔ),后續(xù)會講解JavaScript高級。 重點內(nèi)容 變...

    王軍 評論0 收藏0
  • 前端基礎(chǔ)入門四(JavaScript基礎(chǔ))

    摘要:學(xué)習(xí)目標(biāo)掌握編程的基本思維掌握編程的基本語法我們先來學(xué)習(xí)基礎(chǔ),后續(xù)會講解高級。語句基本語法當(dāng)循環(huán)條件為時,執(zhí)行循環(huán)體,當(dāng)循環(huán)條件為時,結(jié)束循環(huán)?;A(chǔ)語法循環(huán)體循環(huán)條件代碼示例初始化變量循環(huán)體自增循環(huán)條件語句和一般用來解決無法確認(rèn)次數(shù)的循環(huán)。 學(xué)習(xí)目標(biāo): 掌握編程的基本思維 掌握編程的基本語法 我們先來學(xué)習(xí)JavaScript基礎(chǔ),后續(xù)會講解JavaScript高級。 重點內(nèi)容 變...

    SnaiLiu 評論0 收藏0

發(fā)表評論

0條評論

mikyou

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<