1. 程式人生 > 實用技巧 >JS型別轉換之隱式轉換

JS型別轉換之隱式轉換

Boolean()將其他資料型別轉成布林值

  • 0、-0、空字串""、null、undefined、NaN、false、document.all()這8個轉布林值為false,其他的都為true
Boolean(0)    // false
Boolean(-0)    // false
Boolean('')    // false
Boolean(null)    // false
Boolean(undefined)    // false
Boolean(NaN)    // false
Boolean(document.all())    // false
Boolean(' ')    // true
Boolean('-1')    // true
Boolean([])    // true
Boolean({})    // true
Boolean(function(){})    // true
Boolean(Symbol())    // true

Number()將其他資料型別轉成數值

  • null轉為0
  • undefined轉為NaN
  • true轉為1,false轉為0
  • 引用型別先轉成字串然後再轉成數值,字串必須是數字字串才能成功轉成相應的數值,否則都為NaN。空字串""以及只有空格的字串" "轉為0
Number(null)    // 0
Number(undefined)    // NaN
Number(true)    // 1
Number(false)    // 0
Number('')    // 0
Number('   ')    // 0
Number([1])    // 1 [1].toString()返回'1'
Number([1,2])    // NaN [1,2].toString()返回'1,2',轉數值為NaN
Number({})    // NaN ({}).toString()返回'[object Object]',轉數值為NaN

注:事實上引用型別轉數值的過程中會自動呼叫物件的 valueOf()toString()

  • 先呼叫 valueOf(),返回值是基本型別的話,即可轉數值。
  • 如果 valueOf() 的返回值不可直接轉數值的話,再自動呼叫物件的toString(),然後再將得到的字串轉數值。
var obj = {
    valueOf: function(){
        console.log('valueOf方法被呼叫了');
        return '666';
    },
    toString: function(){
        console.log('toString方法被呼叫了');
        return '2333';
    }
}
Number(obj)
// valueOf方法被呼叫了
// 666

var obj = {
    valueOf: function(){
        console.log('valueOf方法被呼叫了');
        return {};
    },
    toString: function(){
        console.log('toString方法被呼叫了');
        return '2333';
    }
}
Number(obj)
// valueOf方法被呼叫了
// toString方法被呼叫了
// 2333

valueOf() 返回物件的原始值

MDN文件
valueOf方法一般都會被 JavaScript 自動呼叫,比如發生隱形轉換時。


String()將其他資料型別轉成字串

String() 和 toString() 效果基本相同,唯一區別就是toString()無法轉換nullundefined

var a;
var b=null;
a.toString();    //Uncaught TypeError: Cannot read property 'toString' of undefined
b.toString();    //Uncaught TypeError: Cannot read property 'toString' of null
String(a);    //"undefined"
String(b);    //"null"

注:引用型別隱形轉換字串時還是遵循先 valueOf() 再 toString(),而不是直接 String()

var obj = {
    valueOf: function(){
        console.log('valueOf方法被呼叫了');
        return '666';
    },
    toString: function(){
        console.log('toString方法被呼叫了');
        return '2333';
    }
}
'00-' + obj    
// valueOf方法被呼叫了
// '00-666'
'00-' + String(obj)    
// toString方法被呼叫了
// '00-2333'

隱式型別轉換場景

+ (字串連線符/算術運算子)

+兩邊有一邊是字串的話,此時+為字串連線符,其他情況則為算術運算子。

  • 字串連線符:將其他資料型別轉成字串,然後進行拼接。
  • 算術運算子:將其他資料型別用Number()轉成數字,然後做加法運算。
1 + '-haha'    // '1-haha'
1 + true    // 2  Number(true)為1
1 + null    // 1  Number(null)為0
1 + undefined    // NaN  Number(undefined)為NaN
1 + {}    // '1[object Object]'  {}轉數字的過程中先轉成了字串,然後就變成了字串拼接
1 + [1,2,3]    // '11,2,3'  原因同上
[] + {}    // '[object Object]'  原因同上
{} + []    // 0  大括號{}在前面被認為是程式碼塊,所以相當於是 +[]

>、<、>=、<= (關係運算符)

會把其他資料型別轉成number數字型別來進行比較,但有些具體情況比較特殊。

  • >、<、>=、<= 的兩邊都是字串的話,比較的是字元的Unicode編碼。
// 一般情況下 Number('2') > 10  false
'2' > 10    // false

// 兩邊都是字串 '2'.charCodeAt() > '10'.charCodeAt()  true
'2' > '10'    // true

// 多個字元依次比較 'a'.charCodeAt() > 'b'.charCodeAt  false
'aac' > 'abc'    // false
<br/>

## ==(關係運算符)
* 型別相同,不發生型別轉換。如果都是引用型別,則比較的是引用地址
* 型別不同,則轉成number數字型別再進行比較
* NaN不與任何值相等,包括NaN自己
```javascript
[1] == [1]    // false
{} == {}    // false
9 == [9]    // true
NaN == NaN    // false

特殊情況:如果資料型別是 null 和 undefined ,結果固定,無規則。

null == null    // true
undefined == undefined    // true
undefined == null    // true

!(邏輯非)

  • 邏輯非,將其他資料型別轉成布林值
  • 邏輯非!優先順序高於關係運算符
// 先算邏輯非,Boolean([])為true => ![]為false => Number(false)為0
![] == 0    // true
// 先算邏輯非,![]為false => Number(false)為0,[].toString()為'' => Number('')為0
[] == ![]    // true
// 先算邏輯非,({}).toString()為'[object Object]' => Boolean('[object Object]') => !{}為false,Number('[object Object]')為NaN
{} == !{}    // false

經典面試題

var a = ???
if(a == 1 && a == 2 && a == 3){
    console.log('少林功夫好嘢');
}
// 如何完善a,使其正確打印出'少林功夫好嘢'

// 分析
// ==會發生隱式轉換
// ==兩邊資料型別不同則轉成Number數字型別來進行比較
// a比較3次3次不同,a只能是引用型別,引用型別轉Number數字型別過程先後自動呼叫valueOf()和toString()
// 經過以上幾步分析,豁然開朗
var a = {
    b: 1,
    valueOf: function(){
        return this.b++;
    }
}
if(a == 1 && a == 2 && a == 3){
    console.log('少林功夫好嘢')
}
// '少林功夫好嘢'

參考文章