类型转换分为两种 强制类型转换和隐式类型转换
强制类型转换
强制类型转换主要指Number()、String()、 Boolean三个函数,手动将各种类型的值,分别转换为数字,字符串或者布尔值
Number()
主要分为两种,一种是参数是原始类型,一种是参数是对象
原值类型的值
//数值,转换后还是原来的值
Number(324) //324
//字符串:如果可以被解析位数值,则转换为相应的数值
Number('324') // 324
//字符串:如果不能解析为数值,返回NaN
Number('324abc')// NaN
//空字符串转换为0
Number('')//0
//布尔值: true为1 false为0
Number(true)//1
Number(false)//0
//undefined 转化为NaN
Number(undefined) // NaN
//null 转为0
Number(null) //0
Number 函数将字符串转为数值,要比parseInt函数严格很多,基本上,只要有一个字符串无法转为数值,整个字符串就会转为NaN
parseInt('42 cat')// 42
Number('42 cat') // NaN
另外。parseInt和Number函数都会自动过滤一个字符串前导和后缀的空格
parseInt('\t\v\r12.34\n') // 12
Number('\t\v\r12.34\n') // 12.34
对象
简单的规则是,Number 方法的参数是对象时,将返回NaN,除非是包含单个数值的数组
Number ({a:1}) // NaN
Number ([1,2,3]) // NaN
Number ([5]) // 5
Number (['1']) // 1
Number ([]) // 0
原因
- 调用对象自身的valueOf 方法,如果返回原始类型的值,则直接对该对象使用Number函数,不在进行后续步骤
- 如果valueOf方法返回的还是对象,则改为调用对象自身的toString 方法,如果toString方法原始类型的值则该对象使用Number函数,不在进行后续步骤
- 如果toString 方法返回的是对象,就报错
var obj = {a:1}
Number(obj) // NaN
等同于
if (typeof obj.valueOf() === 'object') {
Number(obj.toString());
} else {
Number(obj.valueOf());
}
String()
String函数可以将任意类型的值转化为字符串,转换规则如下:
原始类型:
- 数值: 转为为相应的字符串
- 字符串: 不动
- 布尔值: true转换为"true“ false转换为”false“
- undefined: 转换为"undefined"
- null: 转换为“null”
String(123) // "123"
String('abc') // "abc"
String(1e21) // '1e+21'
String(true) // "true"
String(undefined) // "undefined"
String(null) // "null"
对象
string 方法的参数如果是对象,返回一个类型字符串,如果是数组,返回该数组的字符串形式,相当于调用数组的Array.prototype.join() 方法
String({a: 1}) // [object, object]
Strng ([]) // ''
string([1,2,4]) // "1,2,4"
//数组中的null或者undefined,会被当成成空字符串处理
String([1,undefined,3]) // "1,,3"
String 的转换规则与Number方法 基本相同,只是先调用toString方法,在调用valueOf方法
同样toString和valueOf可以自定义
String ({
toString: function () {
return 3;
}
})
// "3"
String ({
valueOf; function () {
return 2;
}
})
// "[object, object]"
String ({
valueOf: function () {
return 2;
},
toString: function () {
return 3;
}
})
// "3"
Boolean()
Boolean() 函数可以将任意类型的值转为布尔值
他的转化规则相对简单,除了以下五个值转化结果为false,其他的值全部为true
- undefined
- null
- 0 (包含-0 和+0)
- NaN
- '' (空字符串)
所有对象(包括空对象)的转化结果都是true.甚至连false 对应的布尔对象new Boolean(false) 也是 true
隐式转换
隐式转换是以强制转换为基础的
遇到一下三种情况时,javascript会自动转换数据类型,
- 第一种,不同类型的数据互相运算
// 其中最常见的就是数字与字符串的运算
//+运算符会将数字转换为字符串,而 - / * 则是将字符串转化为数字
123 + '123' // 123123
123-'123' // 0
'123'/123 // 1
- 对非布尔值类型的数据求布尔值
if('abc') {
console.log('hello')
}除了以下几个值值其他的都是true
undefined null +0 -0 NaN ''(空字符串)
可以使用!运算法将其转换为true
if (! undefined && !null && !0 && !NaN && ! ''){
console.log('hello')
}
//下面这种写法,有时也会讲一个表达式转为布尔值
expression ? true : false
- 对非数值类型使用一元运算符
+ {foo : 'bar'} // NaN
- [1,2,3] // NaN
//在一元运算符中 + 是将与字符串相加转为字符串
'5' + 1 // '51'
'5' + true // "5true"
'5' + false // "5false"
'5' + {} // "5[object Object]"
'5' + [] // "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"
'5' - '2' // 3
'5' * '2' // 10
true - 1 // 0
false - 1 // -1
'1' - 1 // 0
'5' * [] // 0
false / '5' // 0
'abc' - 1 // NaN
null + 1 // 1
undefined + 1 // NaN
js中的 == 与 ===
规则如下:
相等和不相等---先转换在比较 (==)
全等和不全等---仅比较不转换 (===)
== 是对值得比较而 === 不仅比较值还比较类型
==的比较过程
- 如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值 --- false转换为0 true 转换为1
- 如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前想将字符串转换为数值
- 如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型按照前面的规则进行比较
- 如果两个值的类型相同,在比较=== 是否相同
- 如果两个值得类型不同,也有可能比较,会进行类型的隐式转换
- 如果一个是null ,一个是undefined 那么相等
- 如果一个是字符串,一个是数值,把字符串转换为数值之后在进行比较
=== 的比较过程
- 如果类型不同,就一定不相等
- 如果两个都是数值,并且是同一个值,那么相等,如果是NaN则不相等
- 如果两个是字符串,每个位置都一样,那么相等,否则不相等
- 如果两个值都是true,或是false那么相等
- 如果两个值都是null 或者是undefined,那么相等
1 == 1 // true
1 === Number(1) // false
NaN == NaN // false
null == undefined // true
1 == '1' //true
1 === '1' // false
'9'< '10' // false 字符串的标胶按位比较, 数字字符比较的ASIC码,没有数字的asic只有0-9 48- 57
大写字符的顺序是 65-90 小写字符的顺序是 97-122
typeof [] === 'array' // false typeof 只能判断基本类型,对象只能判断出 object typeof [] 的结果为 object
'null' == 'undefined' // false 这是字符串的比较
[] == ![] // true
{} == !{} // false
根据运算符优先级, !的优先级是大于== 的 所以会先执行![]
!运算符会将转换为boolean类型,其中 null, undefined, NaN,(' ')为false 其余都是true
所以 ![]的结果是false
根据上面的规则(如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值) 那么 ![] = false = 0
那么比较变成了 [] == 0
再根据上面的规则 (如果一个操作数是对象另一个操作数不是,则调用该对象的valueOf()方法,获取其值,用得到的基本类型按照前面的规则比较,如果对象没有valueOf()方法,则调用toString() 方法)
而对于空数组,[].toString() -> '' (返回的是空字符串)
则比较变成了 '' == 0
再根据上面的规则 (如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前将字符串转换为数值)
Number ('') -> 0
则变成了 0 == 0 // true
总结如下:
[] == ![] -> [] == false -> [] == 0 -> '' == 0 -> 0 == 0 -> true
那么对于 {} == !{} 也是同理
关键在于 {}.toString() -> NaN
{} ==!{} -> {} == false -> {} == 0 -> NaN == 0 -> false