国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

從0開始構建自己的前端知識體系-不要對"=="說不

tianyu / 1610人閱讀

摘要:為了避免某些場景下的意外,甚至推崇直接使用來代替。使用了運算符的一些規則,發生了類型轉換。按照以下規則轉換被傳遞參數直接返回直接返回直接返回直接返回直接返回返回一個對象的默認值。

前言

類型轉換在各個語言中都存在,而在 JavaScript 中由于缺乏對其的了解而不慎在使用中經常造成bug被人詬病。為了避免某些場景下的意外,甚至推崇直接使用 Strict Equality( === )來代替 ==。這確實能避免很多bug,但更是一種對語言不理解的逃避(個人觀點)。

引入

先拋出在 You Don"t Know JavaScript (中) 看到的一個例子

  [] == [] // false
  [] == ![] // true
  {} == !{} // false
  {} == {} // false

是不是很奇怪?本文將從書中看到的知識與規范相結合,來詳細說明一下JavaScript在類型轉換時候發生的故事。

類型轉換

很多人喜歡說顯示類型轉換與隱式類型轉換,但個人感覺只是說法上的不同,實質都在發生了類型轉換而已,故不想去區分他們了(感覺一萬個人有一萬種說法)

僅在6大基本類型 null undefined number boolean string object 作討論 symbol未考慮

舉個栗子

var a = String(1)
var b = Number("1")
var c = 1 + ""
var d = +"1"

a,b直接調用了原生函數,發生了類型轉換。c,d使用了+運算符的一些規則,發生了類型轉換。這些是很簡單的也是我們常用的。

其實真正起作用的,是語言內部對規范中抽象操作的實現,接下來我們所說的 ToString, ToNumber, ToBoolean 等都是抽象操作,而不是JS里對應的內置函數

ToString - 規范9.8

按照以下規則轉化被傳遞的參數

Argument Type Result
Undefined "undefined"
Null "null"
Boolean true -> "true"
false - > "false"
Number NaN -> "NaN"
+0 -0 -> "0"
-1 -> "-1"
infinity -> "Infinity"
較大的數科學計數法 (詳見規范9.8.1)
String 不轉換 直接返回
Object 1. 調用ToPrimitive抽象操作, hint 為 String 將返回值作為 value
2. 返回ToString(value)
String(undefined) // "undefined"
String(null) // "null"
String(true) // "true"
ToPrimitive 抽象操作下面會提及

ToNumber - 規范9.3

按照以下規則轉換被傳遞參數

Argument Type Result
Undefined NaN
Null +0
Boolean true -> 1
false -> +0
Number 直接返回
String 如果不是一個字符串型數字,則返回NaN(具體規則見規范9.3.1)
Object 1. 調用ToPrimitive抽象操作, hint 為 Number 將返回值作為 value
2. 返回ToNumber(value)

ToBoolean - 規范9.2

按照以下規則轉換被傳遞參數

Argument Type Result
Undefined false
Null false
Boolean 直接返回
Number +0 -0 NaN -> false
其他為true
String 空字符串(length為0) -> false
其他為true
Object true

ToPrimitive - 規范9.1

顧名思義,該抽象操作定義了該如何將值轉為基礎類型(非對象),接受2個參數,第一個必填的要轉換的值,第二個為可選的hint,暗示被轉換的類型。

按照以下規則轉換被傳遞參數

Argument Type Result
Undefined 直接返回
Null 直接返回
Boolean 直接返回
Number 直接返回
String 直接返回
Object 返回一個對象的默認值。一個對象的默認值是通過調用該對象的內部方法[[DefaultValue]]來獲取的,同時傳遞可選參數hint。

[[DefaultValue]] (hint) - 規范8.12.8

當傳遞的hint為 String 時候,

如果該對象的toString方法可用則調用toString

如果toString返回了一個原始值(除了object的基礎類型)val,則返回val

如果該對象的valueOf方法可用則調用valueOf方法

如果valueOf返回了一個原始值(除了object的基礎類型)val,則返回val

拋出TypeError的異常

當傳遞的hint為 Number 時候,

如果該對象的valueOf方法可用則調用valueOf方法

如果valueOf返回了一個原始值(除了object的基礎類型)val,則返回val

如果該對象的toString方法可用則調用toString

如果toString返回了一個原始值(除了object的基礎類型)val,則返回val

拋出TypeError的異常

hint的默認值為Number,除了Date object

舉個栗子

var a = {}
a.toString = function () {return 1}
a.valueOf = function () {return 2}
String(a) // "1"
Number(a) // 2
a + "" // "2"   ???????
+a // 2
a.toString = null
String(a) // "2"
a.valueOf = null
String(a) // Uncaught TypeError: balabala

似乎我們發現了一個很不合規范的返回值,為什么 a + ""不應該返回"1"嗎

問題的答案其實很簡單 + 操作符會對兩遍的值進行 toPrimitive 操作。由于沒有傳遞 hint 參數,那么就會先調用a.valueOf 得到2后因為+右邊是字符串,所以再對2進行ToString抽象操作后與""的字符串拼接。

不要畏懼使用 ==

基礎概念已經了解了,那么在 == 中到底發生了什么樣的類型轉換,而導致了經常產生出乎意料的bug,導致了它臭名昭著。

抽象相等 - 規范11.9.3

x == y 判斷規則如下:

如果xy類型相同 (與嚴格相等判斷一致,不贅述了,詳見規范)

如果 x 為 null y 為 undefined, 返回true

如果 x 為 undefined y 為 null, 返回true

如果 x 類型為 Number, y 類型為 String, 返回 x == ToNumber(y)

如果 x 類型為 String, y 類型為 Number, 返回ToNumber(x) == y

如果 x 類型為 Boolean, 返回 ToNumber(x) == y

如果 y 類型為 Boolean, 返回 x == ToNumber(y)

如果 x 類型為 String 或 Number, y 類型為 Object, 返回 x == ToPrimitive(y)

如果 x 類型為 Object, y 類型為 String 或 Number, 返回 ToPrimitive(x) == y

return false

再看引入

  [] == [] // false
  // 1. 兩遍類型都為 Object,比較引用地址,不同返回false 搞定
  [] == ![] // true
  // 1. ![]強制類型轉換 變為 [] == false
  // 2. 根據規范第7條,返回 [] == ToNumber(false), 即 [] == 0
  // 3. 根據規范第9條,返回ToPromitive([]) == 0,數組的valueOf為本身,不是原始值,則返回toString()即 "" == 0
  // 4. 根據規范第5條,返回ToNumber("") == 0, 即 0 == 0
  // 5. 根據規范第1條,返回 true

  // 下面的不贅述了,分析類似上面
  {} == !{} // false
  {} == {} // false

我們不難看出以下幾點

其實在x y類型相同的時候,== 與 === 沒有任何區別。

除了undefined與null, 大多數值都會轉換為相同類型后進行對比,也就是說 === 是 == 某些情況下必經的步驟

引用 << 你不知道的JS(中) >> 中的2句話

如果兩遍的值中有 true 或者 false , 千萬不要使用 == (會被轉為數字0,1來進行判斷,會出現一些意外的情況)

如果兩遍的值中有[]、""或者0,盡量不要使用 ==

抽象比較

先來看看這個例子

var a = { b: 42 }
var b = { b: 43 }
a < b // false
a == b // false
a > b // false

a <= b // true
a >= b // true

是不是感覺到世界又崩塌了???

讓我們來仔細分析一下

var a = { b: 42 }
var b = { b: 43 }
a < b // false 
// 1. 兩遍調用ToPrimitive, 返回[object Object] 兩遍一致 返回 false
a == b // false
// 兩遍不同的引用,返回false
a > b // false
// 同 a < b

a <= b // true
// 按規范其實是處理成 !(a > b) 所以為true
a >= b // true

所以在不相等比較的時候,我們最后還是進行手動的類型轉換較為安全

總結

深入了解類型轉換的規則,我們就可以很容易取其精華去其糟粕,寫出更安全也更簡潔可讀的代碼。

參考

你不知道的JS(中)

ecma-262 5.1規范

如果喜歡可以star一下,會不斷更新github地址

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95058.html

相關文章

  • 如何&quot;有計劃,高效率,優簡歷&quot;應面試

    摘要:雖然有了十全的計劃,但如何高效率去記住上面那么多東西是一個大問題,看看我是怎么做的。 前言 前一篇文章講述了我在三月份毫無準備就去面試的后果,一開始心態真的爆炸,但是又不服氣,一想到每次回來后家人朋友問我面試結果的期待臉,越覺得必須付出的行動來證明自己了。 面經傳送門:一個1年工作經驗的PHP程序員是如何被面試官虐的? 下面是我花費兩個星期做的準備,主要分三部分: 有計劃——計劃好...

    gyl_coder 評論0 收藏0
  • 使用 &quot;5W1H&quot; 寫出高可讀 Git Commit Message

    摘要:共字,讀完需分鐘。下面提出一種可以幫你寫出高可讀的實踐方法,這個方法并非原創,最早的實踐來自于這篇文章。本文作者王仕軍,商業轉載請聯系作者獲得授權,非商業轉載請注明出處。 showImg(https://segmentfault.com/img/remote/1460000009341335?w=1240&h=403); 共 1926 字,讀完需 4 分鐘。所有工程師都知道,代碼是編寫...

    DevYK 評論0 收藏0
  • Html/Css/Jquery知識點集錦

    摘要:首先,巧妙的使用這一標記,將游覽器從所有情況中分離出來。接著,再次使用將和分離開來,這樣已經獨立識別。元素不能用作語義用途以外的其他目的。Html1、Html5有哪些新特性,移除了哪些元素?如何處理HTML5新標簽的瀏覽器兼容問題?如何區別HTML和HTML5?HTML5 現在已經不是 SGML 的子集,主要是關于圖像,位置,存儲,多任務等功能的增加。拖拽釋放(Drag and drop) ...

    shiweifu 評論0 收藏0
  • 《HelloGitHub》第 68 期

    摘要:整個項目簡單還具有實用價值,可作為的實戰項目學習的調試工具欄。查看文檔自動在個人首頁展示編程時長的工具。通過學習這些前沿的人工智能論文,提前了解在未來更多可能性可以將圖片和視頻轉換成漫畫風格的工具。興趣是最好的老師,HelloGitHub 讓你對編程感興趣!簡介HelloGitHub 分享 GitHub 上有趣、入門級的開源項目。https://github.com/521xueweihan...

    番茄西紅柿 評論0 收藏2637

發表評論

0條評論

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