前言:整理給自己的材原,方便復(fù)習(xí)沸久,不喜勿噴,有錯(cuò)誤歡迎指出余蟹。
一卷胯、隱式轉(zhuǎn)換介紹
隱式轉(zhuǎn)換是指在JavaScript中,當(dāng)運(yùn)算符在運(yùn)算時(shí)威酒,如果兩邊數(shù)據(jù)不統(tǒng)一窑睁,CPU就無(wú)法計(jì)算,這時(shí)我們編譯器會(huì)自動(dòng)將運(yùn)算符兩邊的數(shù)據(jù)做一個(gè)數(shù)據(jù)類型轉(zhuǎn)換葵孤,轉(zhuǎn)成一樣的數(shù)據(jù)類型再計(jì)算担钮。這種無(wú)需程序員手動(dòng)轉(zhuǎn)換,而由編譯器自動(dòng)轉(zhuǎn)換的方式就稱為隱式轉(zhuǎn)換尤仍。
1 > "0" 這行代碼在js中并不會(huì)報(bào)錯(cuò)箫津,編譯器在運(yùn)算符時(shí)會(huì)先把右邊的"0"轉(zhuǎn)成數(shù)字 0 然后在比較大小
二、隱式轉(zhuǎn)換規(guī)則
轉(zhuǎn)為String類型: +(字符串連接符)
轉(zhuǎn)為Number類型:++ / -- (自增自減運(yùn)算符) + - * / %(算術(shù)運(yùn)算符) > < >= <= == != === !== (關(guān)系運(yùn)算符)
轉(zhuǎn)為Boolean類型:宰啦!(邏輯非運(yùn)算符)
轉(zhuǎn)為布爾類型成為false的有:undefined苏遥、null、空字符串赡模、0田炭、-0、NaN
new Number() 和 Number() 是不同的漓柑,new Number() 創(chuàng)建了一個(gè)Number對(duì)象教硫,Number() 將傳入的參數(shù)轉(zhuǎn)換為數(shù)值字面量
1 + "true" // "1true" 若+兩邊存在一個(gè)字符串,將另一個(gè)也轉(zhuǎn)為字符串進(jìn)行字符串拼接 String(1) + "true" = "1true"
1 + true // 2 這里的 + 是算術(shù)運(yùn)算符 1 + Number(true) = 1 + 1 = 2
1 + undefined // NaN 這里的 + 是算術(shù)運(yùn)算符 1 + Number(undefined) = 1 + NaN = NaN
1 + null // 1 這里的 + 是算術(shù)運(yùn)算符 1 + Number(null) = 1 + 0 = 1
PS:不要混淆字符串連接符與算術(shù)運(yùn)算符隱式轉(zhuǎn)換規(guī)則
再來(lái)看幾個(gè)例子
“2” > 10 // false Number(2) > 10 = 2 > 10 = false
"2" > "10" // true 當(dāng)兩邊都是字符串的時(shí)候欺缘,此時(shí)轉(zhuǎn)為number然后比較關(guān)系栋豫,注意這里并不是按照Number()的形式轉(zhuǎn)為數(shù)字挤安,而是按照字符串對(duì)應(yīng)的unicode編碼來(lái)轉(zhuǎn)成數(shù)字谚殊,charCodeAt(index) index為字符下標(biāo),默認(rèn)為0蛤铜。
"2".charCodeAt(0) > '10'.charCodeAt(0) = 50 > 49 = true
"abc" > "b" // false 多個(gè)字符的時(shí)候從左往右依次比較 'a'.charCodeAt(0) = 97 'b'.charCodeAt(0) = 98
"abc" > "aad" // true
NaN == NaN // false
特殊情況:如果數(shù)據(jù)類型是undefined或null 得出固定結(jié)果
undefined == undefined // true
undefined == null // true
null == null // true
NaN == NaN // false
三嫩絮、對(duì)象的類型轉(zhuǎn)換
1、對(duì)象到字符串的轉(zhuǎn)換( 這里說(shuō)的是String()方法的原理 )
若具有toString()
方法围肥,調(diào)用toString()
剿干,如果它返回一個(gè)原始值
,將這個(gè)原始值轉(zhuǎn)換為字符串
返回
若無(wú)toString()
方法穆刻,或toString()的返回值并不是一個(gè)原始值
置尔,尋找其valueOf()
方法,若存在這個(gè)方法氢伟,調(diào)用它榜轿,如果它返回一個(gè)原始值
幽歼,將這個(gè)原始值轉(zhuǎn)換為字符串
返回
否則(無(wú)valueOf()
或valueOf()
的返回值不是原始值),JS無(wú)法從toString()或valueOf()方法獲得一個(gè)原始值
谬盐。因此甸私,throw TypeError
2、對(duì)象到數(shù)字的轉(zhuǎn)換(這里說(shuō)的是Number()
方法的原理)
若具有valueOf()
方法飞傀,調(diào)用valueOf()
皇型,如果它返回一個(gè)原始值
,將這個(gè)原始值轉(zhuǎn)換為數(shù)字
返回
若無(wú)valueOf()
方法砸烦,或valueOf()的返回值并不是一個(gè)原始值
弃鸦,尋找其toString()
方法,若存在這個(gè)方法外冀,調(diào)用它寡键,如果它返回一個(gè)原始值
,將這個(gè)原始值轉(zhuǎn)換為數(shù)字
返回
否則(無(wú)toString()
或toString()
的返回值不是原始值)雪隧,JS無(wú)法從toString()或valueOf()方法獲得一個(gè)原始值
西轩,因此,throw TypeError
對(duì)象到數(shù)字的轉(zhuǎn)換和對(duì)象到字符串的轉(zhuǎn)換類似脑沿,只是兩個(gè)方法的調(diào)用順序不同
3藕畔、對(duì)象到布爾值的轉(zhuǎn)換
對(duì)象類型轉(zhuǎn)換為布爾值:均為true
,不管其toString()庄拇、valueOf()方法返回什么
數(shù)組類型的轉(zhuǎn)換實(shí)際上也遵循以上三條注服,不過(guò)它覆蓋了原型鏈上的toString()方法,改為返回`數(shù)組的join()`方法的返回結(jié)果
4措近、各類型的toString()溶弟、valueOf()方法的返回值
對(duì)象(Object
)
toString()返回: “[object Object]”
valueOf()返回: 對(duì)象本身
var a = { b: 1 }
a.toString() ? "[object Object]"
a.valueOf() ? {b: 1}
數(shù)組(Array
)
toString()返回: this.join()的返回值
valueOf()返回: 數(shù)組本身
var a = [1,2,3]
a.toString() ? "1,2,3"
a.valueOf() ? [1, 2, 3]
方法(Function
)
toString()返回: 整個(gè)函數(shù)字符串
valueOf()返回: 方法本身
var a = function () { b =333; return 111; }
a.toString() ? "function(){b =333; return 111;}"
a.valueOf() ? ? () { b =333; return 111; }
日期(Date
)
toString()返回:完整事件字符串
valueOf()返回:從1970年1月1日0時(shí)0分0秒(UTC,即協(xié)調(diào)世界時(shí))到該日期的毫秒數(shù)瞭郑。
var a = new Date()
a.toString() ? "Thu Mar 07 2019 13:48:31 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間)"
a.valueOf() ? 1551937711874
Error
toString()返回:"Error {錯(cuò)誤描述}"
valueOf()返回:錯(cuò)誤本身
正則(RegExp
)
toString()返回:正則式完整字符串
valueOf()返回:正則本身
var a = new RegExp('^ass[^f]\w?','gi')
a.toString() ? "/^ass[^f]\w?/gi"
a.valueOf() ? /^ass[^f]\w?/gi“
四辜御、總結(jié)和實(shí)踐!
1、 算術(shù)運(yùn)算符(+屈张、-擒权、*、/阁谆、++碳抄、–、%…)
'+'
作為一個(gè)雙目運(yùn)算符: 若+兩邊存在一個(gè)字符串
场绿,將另一個(gè)也轉(zhuǎn)為字符串進(jìn)行字符串拼接剖效。
其他情況下,不管雙目還是單目,都轉(zhuǎn)為數(shù)值
類型
2璧尸、關(guān)系運(yùn)算符(>劝贸、<、==逗宁、!=…)
===映九、!==
:同時(shí)對(duì)比類型和值,兩個(gè)都為真才返回真
==瞎颗、!=
: 若兩邊均為對(duì)象件甥,對(duì)比它們的引用是否相同
!(邏輯非)
: 將其后變量或表達(dá)式轉(zhuǎn)為布爾值
對(duì)比字符串
:從頭至尾掃描逐個(gè)比較每個(gè)字符的unicode
碼,直到分出大小
其他情況下哼拔,兩邊均轉(zhuǎn)為數(shù)值類型
NaN與任何值都不相同引有,與任何值比較都返回false
對(duì)象類型在運(yùn)算時(shí)進(jìn)行類型轉(zhuǎn)換都先調(diào)用valueOf()方法,再嘗試toString()方法
在進(jìn)行對(duì)象字面量(這里說(shuō)的是JSON格式的對(duì)象字面量)運(yùn)算時(shí)要注意倦逐,若運(yùn)算符兩邊都是字面量譬正,
則將它們都視為對(duì)象字面量進(jìn)行類型轉(zhuǎn)換;
若只有一個(gè)字面量時(shí)要注意檬姥,當(dāng)這個(gè)字面量在首位時(shí)曾我,會(huì)被當(dāng)做一個(gè)塊看待。
{} + {} => "[object Object][object Object]"
{}被當(dāng)做一個(gè)塊健民,相當(dāng)于執(zhí)行 ( {}, +[] )抒巢,計(jì)算的是+[]的結(jié)果
{} + [] => 0
{ a: 1 } + [] => 0
{} == [] => 報(bào)錯(cuò) ({}, ==[]) => 報(bào)錯(cuò)
變量形式運(yùn)算正常
var a = { q:1 }
a + [] => "[object Object]"
[] + a => "[object Object]"
[1,2,3] + [] => "1,2,3" + "" => "1,2,3"
[] + {} => "" + "[object Object]" => "[object Object]"
[] == 0 // true [] => "" => 0
![] == 0 // true ![] => false => 0
[] == ![] // true [] => "" => 0 ![] => false => 0
[] == [] // false 比較引用地址
{} == {} // false 比較引用地址
{} == !{} // false !{} => false => 0 {} => "[object Object]" => Number("[object Object]") => NaN
如果你想了解更多,可以閱讀原文JavaScript類型轉(zhuǎn)換原理性的問(wèn)題 或者譯文JavaScript類型轉(zhuǎn)換原理性的問(wèn)題