相信剛開始瞭解js的時候,都會遇到 2 =='2',但 1+2 == 1+'2'爲false的狀況。這時候應該會是一臉懵逼的狀態,不得不感慨js弱類型的靈活讓人髮指,類型轉換就是這麼猝不及防。結合實際中的狀況來看,有意或無心中涉及到類型轉換的狀況仍是不少的。既然要用到,就須要掌握其原理,知其然重要知其因此然更重要。git
JavaScript 是弱類型語言,意味着JavaScript 變量沒有預先肯定的類型。
而且變量的類型是其值的類型。也就是說變量當前的類型由其值所決定,誇張點說上一秒種的string,下一秒可能就是個array了。此外當進行某些操做時,變量能夠進行類型轉換,咱們主動進行的就是顯式類型轉換,另外一種就是隱式類型轉換了。例如:es6
var a = '1';
typeof a;//string
a =parseInt(a); //顯示轉換爲number
typeof a //number
a == '1' //true
複製代碼
弱類型的特性在給咱們帶來便利的同時,也會給咱們帶來困擾。趨利避害,充分利用該特性的前提就是掌握類型轉換的原理,下面一塊兒看一下。github
老生常談的兩大類數據類型:算法
0 | Number |
---|---|
'' | String |
false | Boolean |
null | Null |
undefined | Undefined |
對於不一樣的數據格式轉換規則是不一樣的,咱們須要分別對待。學習
既然是規範定義的規則,那就不要問爲何了,先大體看一下,爭取記住。是在不行常常翻翻看看大佬的博客es5規範。轉換有下面這麼幾類,咱們分別看一下具體規範。(這部分轉換規則,徹底能夠跳過去,看到下面的實例再回頭看應該更容易接受一些)ui
ToPrimitive 運算符接受一個值,和一個可選的 指望類型 做參數。ToPrimitive 運算符把其值參數轉換爲非對象類型。若是對象有能力被轉換爲不止一種原語類型,可使用可選的 指望類型 來暗示那個類型。根據下表完成轉換
this
這段定義看起來有點枯燥。轉換爲原始值,其實就是針對引用數據的,其目的是轉換爲非對象類型。
若是已是原始類型,固然就不作處理了
對於object,返回對應的原始類型,該原始類型是由指望類型決定的,指望類型其實就是咱們傳遞的type。直接看下面比較清楚。
ToPrimitive方法大概長這麼個樣子具體以下。es5
/** * @obj 須要轉換的對象 * @type 指望轉換爲的原始數據類型,可選 */
ToPrimitive(obj,type)
複製代碼
type能夠爲number或者string,二者的執行順序有一些差異
string:spa
number:3d
其實就是調用方法前後,畢竟指望數據類型不一樣,若是是string固然優先調用toString。反之亦然。
固然type參數能夠爲空,這時候type的默認值會按照下面的規則設置
對於Date數據類型,咱們更多指望得到的是其轉爲時間後的字符串,而非毫秒值,若是爲number,則會取到對應的毫秒值,顯然字符串使用更多。 其餘類型對象按照取值的類型操做便可。
歸納而言,ToPrimitive轉成何種原始類型,取決於type,type參數可選,若指定,則按照指定類型轉換,若不指定,默認根據實用狀況分兩種狀況,Date爲string,其他對象爲number。那麼何時會指定type類型呢,那就要看下面兩種轉換方式了。
某些特定狀況下須要用到ToNumber方法來轉成number 運算符根據下表將其參數轉換爲數值類型的值
對於string類型,狀況比較多,只要掌握常見的就好了。和直接調用Number(str)的結果一致,這裏就很少提了,主要是太多提不完。
須要注意的是,這裏調用ToPrimitive的時候,type就指定爲number了。下面的toString則爲string。
ToString 運算符根據下表將其參數轉換爲字符串類型的值:
其實瞭解也很簡單,畢竟是個規範,借用大佬一張圖:
雖然是須要死記的東西,仍是有些規律可循的。 對於原始值:
當調用 valueOf 方法,採用以下步驟:
不一樣內置對象的valueOf實現:
對照代碼更清晰一點
var str = new String('123')
//123
console.log(str.valueOf())
var num = new Number(123)
//123
console.log(num.valueOf())
var date = new Date()
//1526990889729
console.log(date.valueOf())
var bool = new Boolean('123')
//true
console.log(bool.valueOf())
var obj = new Object({valueOf:()=>{
return 1
}})
//依賴於內部實現
console.log(obj.valueOf())
複製代碼
前面提了那麼多抽象概念,就是爲了這裏來理解具體轉換的。
對於+運算來講,規則以下:
1+'2'+false
複製代碼
咱們看一個複雜的
var obj1 = {
valueOf:function(){
return 1
}
}
var obj2 = {
toString:function(){
return 'a'
}
}
//2
console.log(1+obj1)
//1a
console.log('1'+ obj2)
//1a
console.log(obj1+obj2)
複製代碼
無論多複雜,按照上面的順序來吧。
到這裏相信你們對+這種運算的類型轉換了解的差很少了。下面就看一下另外一種隱式類型轉換
這種比較分爲兩大類,
若是x,y均爲number,直接比較
沒什麼可解釋的了
1 == 2 //false
複製代碼
若是存在對象,ToPrimitive() type爲number進行轉換,再進行後面比較
var obj1 = {
valueOf:function(){
return '1'
}
}
1 == obj2 //true
//obj1轉爲原始值,調用obj1.valueOf()
//返回原始值'1'
//'1'toNumber獲得 1 而後比較 1 == 1
[] == ![] //true
//[]做爲對象ToPrimitive獲得 ''
//![]做爲boolean轉換獲得0
//'' == 0
//轉換爲 0==0 //true
複製代碼
存在boolean,按照ToNumber將boolean轉換爲1或者0,再進行後面比較
//boolean 先轉成number,按照上面的規則獲得1
//3 == 1 false
//0 == 0 true
3 == true // false
'0' == false //true
複製代碼
若是x爲string,y爲number,x轉成number進行比較
//'0' toNumber()獲得 0
//0 == 0 true
'0' == 0 //true
複製代碼
ECMAScript5.1中文版 + ECMAScript3 + ECMAScript(合集)
你所忽略的js隱式轉換
這篇文章的本意是爲本身解惑,寫到後面真的感受比較乏味,畢竟規範性的東西多一點,不過深刻了解一下總好過死記硬背。原文請移步個人博客。對於有些觀點說這些屬於js糟粕,徹底不該該深刻,怎麼說呢,結合本身狀況判斷吧。本人水平有限,拋磚引玉共同窗習。