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 自动调用,比如发生隐形转换时。
JS类型转换之隐式转换

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(‘少林功夫好嘢‘)
}
// ‘少林功夫好嘢‘

参考文章

JS类型转换之隐式转换

上一篇:IDE - idea - tab - 方法相关的移动


下一篇:Custom Roles Based Access Control (RBAC) in ASP.NET MVC Applications - Part 1 (Framework Introduction)