一、抽象值操作
JavaScript中隐式类型转换总是返回基本类型值,如字符串、数字、布尔
值,不会返回对象或者函数。
(1)ToString():负责处理非字符串到字符串的强制类型转换。
基本类型的值转化为字符串的基本规则:
-
null转化为"null"
undefined转化为"undefined"
true转化为"true"
数字的字符串转化规则遵循通用规则
对于普通对象来说,如果没有自定义toString()方法,返回"[objec Object]"。如果有自己的toString()方法就会调用该方法并返回值。
数组的toString()返回所有单元字符串化以后再用","连接起来:
var a = [1,2,3] a.toString() // "1,2,3"
日期、正则、函数也遵循通用规则。
(2)ToNumber()
基本类型的值转化为数字的基本规则:
-
null转化为0
undefined转化为NaN
true转化为1,false转化为0
字符串的处理遵循通用规则
Number("23") // 23 Number("") // 0
对象或者数组首先会被转化为相应的基本类型,如果返回的是非数字的基本类型,再按照以上规则进行转化。其中对象转化为基本类型的时候会使用ToPrimitive操作。
(3)ToPrimitive()
ToPrimitive操作会首先检查对象是否有valueOf()方法,如果有并且返回基本类型的值,就调用该方法进行类型转化。 如果没有就使用toString()返回的值。 若valueOf()和toString()均不返回基本类型值,就会产生TypeError错误。如果不对对象和数组的valueOf()和toString()方法进行重写,那么:-
对象的valueOf()返回对象本身,toString()返回"[object Object]"
数组的valueOf()返回数组本身,toString()返回所有单元字符串化以后再用","连接起来。
var a = { name: 'sillywa'}var b = [1,2,3]a.valueOf() // { name: 'sillywa' } a.toString() // "[object Object]"b.valueOf() // [1,2,3]b.toString() // "1,2,3"
(4)ToBoolean()
null 转化为false Boolean(null) // false
undefined转化为false Boolean(undefined) // false
除""以外,所有字符串转化为true
Boolean("") // fasleBoolean("abc") // true Boolean('0') // true
除0(包括+0和-0)和NaN外,所有数字转化为true
Boolean(0) // false
Boolean(NaN) // false
Boolean(-9) // true
所有对象转化为true
Boolean({}) // true
Boolean([]) // true
// 需要注意的是通过new关键字得到的是一个对象var a = new Boolean(false)var b = new Number(0)var c = new String('')var d = Boolean(a && b && c)d // true
二、隐式类型转换
字符串运算符跟算术运算符隐式转换规则混淆:
console.log( 1 + "true") // '1true'// +是字符串连接符:String(1) + true = '1true'console.log(1+true) // 2//+是算术运算符:1+ Number(true) = 1 + 1 = 2console.log(1+undefined) // NaN// + 是算术运算符:1 + Number(undefined) = 1 + NaN = NaNconsole.log(1+null) // 1// + 是算术运算符:1 + Number(null) = 1 = 0 = 1
关系运算符:
console.log("2" > 10) // false// 当关系运算符两边有一边是字符串的时候,会将其他数据类型使用Number()转成,然后在比较:Number('2') > 10 = 2 > 10 = flaseconsole.log("2" > "10") // true// 当关系运算符两边都是字符串的时候,此时同时成number型比较关系。重点是:此时需按照字符串对应的Unicode编码来转成数字:'2'.charCodeAt() > '10'.charCodeAt() = 50 > 49 = trueconsole.log("abc" > "b") // false// 多个字符从左往右一次比较,先比较'a' 和 'b' 不等,直接得出结果:'a'.charCodeAt() > 'b'.charCodeAt() = 97 > 98 = falseconsole.log("abc" > "aad") // true// 先比较'a' 和 'a' 相等,继续比较下一个字符 'b' 和 'a' : 'b'.charCodeAt() > 'a'.charCodeAt() = 98 > 97 = trueconsole.log(NaN == NaN) // false// 特殊情况(无视规则):NaN与任何数据比较都是NaNconsole.log(undefined == undefined) // trueconsole.log(undefined == null) // trueconsole.log(null == null) // true// 特殊情况(无视规则):如果数据类型是undefined与null,得出固定结果。
逻辑非隐式转换与关系运算符隐式转换搞混淆:
console.log([] == 0) // true// [].valueOf().toString()结果为空字符串,Number(' ') = 0console.log( ![] == 0 ) // true// 原理:本质是 ' ![] '逻辑非表达式结果与 0 比较关系// 逻辑非优先级高于关系运算符 ![] = flase(空数组转换boolean值为true,然后取反得到false)// Number(false) = 0console.log([] == ![]) // true// 原理:本质是[] 与 ' ![] ' 逻辑非表达式结果比较// (1) [].valueOf().toString() = ' '// (2) ![] = false// (3) Number( ' ' ) = Number(false)console.log( [] == []) // false// 引用类型数据存储在堆中,比较的是存储地址,所以两者不相等console.log( {} == {} ) // false 同上console.log( {} == !{} ) // false// 本质:{} 与 !{} 逻辑非表达式作比较// (1) {}.valueOd().toString() = '[object Object]'// (2) Number('[object Obejct]') = NaN// (3) !{} = false Number(false) = 0
以上就是所有内容啦,欢迎给出您宝贵的建议和意见