这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战
类型转换(2)
01. 对象的转换
-
在没有
toString()方法和valueOf()方法的情况下- 对象转换为字符串,会返回
[object Object] - 对象转换为数值,会返回
NaN
- 对象转换为字符串,会返回
-
如果有相应的方法,那么,对象在转换为基本类型时,可以调用
valueOf方法或者toString方法来进行转换,具体步骤如下:-
如果有
valueOf()方法-
如果它返回一个基本类型值(原始类型值),则会直接返回
-
如果返回的不是一个基本类型值,则调用
toString()方法
-
-
如果没有
valueOf()方法- 则会调用
toString()方法
- 则会调用
-
如果有
toString()方法-
如果返回的是基本类型值,则直接返回
-
如果返回的不是基本类型值,那即说明对象无法转换为字符串,最后会抛出一个错误,表示无法转换对象为字符串
-
注意顺序:
- 在使用对象运算时,和,在使用
Number()转换为数值时- 遵循先调用
valueOf(),再调用toString()
- 遵循先调用
- 在使用
String()转换为字符串- 遵循先调用
toString(),再调用valueOf()
- 遵循先调用
-
let obj = {
a: 1,
valueOf(){
console.log('valueOf')
return []
},
toString(){
console.log('toString')
return 2
}
}
// 1. 使用对象进行运算
console.log(obj + 1)
// 先调用 valueof(),返回 [] ,不是一个基本类型值
// 继续调用 toString(), 返回 2 ,数值类型
// 计算 2 + 1 = 3
// 结果—— 打印:valueof toString ;返回:3
// 2. 使用 Number() 转换为数值
console.log(Number(obj))
// 先调用 valueof(),返回 [] ,不是一个基本类型值
// 继续调用 toString(), 返回 2 ,数值类型
// 结果—— 打印:valueof toString ;返回:2
// 3. 使用 String() 转换为字符串
console.log(String(obj))
// 先调用 toString() ,返回 2 ,数值类型
// 结果—— 打印:toString ;返回:2
// 4. 直接调用相应方法
console.log(obj.toString()) // 打印:toString ;返回: 2
console.log(obj.valueOf()) // 打印:valueOf ;返回: []
-
这两个方法都是可以重写的
- 另外,还可以重写对象的这个方法:
[Symbol.toPrimitive],这个方法在转换基本类型时优先级最高
let obj = { num: 1, // 优先级最高 [Symbol.toPrimitive](){ return 3 }, valueOf(){ return 2 }, toString(){ return '1' } } // [Symbol.toPrimitive]优先级最高,所以返回 3 console.log(obj + 0) // 3 console.log(obj + '0') // '30' // 如果没有这三个方法,则返回 [object Object] console.log(obj + 0) // [object Object]0 console.log(obj - 0) // NaN - 另外,还可以重写对象的这个方法:
-
特别的,还可以在转换时进行一些操作
let obj = { num: 1, [Symbol.toPrimitive]() { return this.num++ } } console.log(obj == 1 && obj == 2 && obj == 3) // true
02. 数组转换
-
对于数组,在转换为基本类型时
-
如果为空数组:则转换字符串为
'',转换为数值型为0 -
如果只有一个值:则转换为对应字符串,转换为数值型按数值类型转换规则
-
如果有多个值:可以转换为字符串,但无法转换为数值类型
但也可以重写其
toString、toPrimitive方法(通过直接赋值的方法改变)let arr = [1, 2, 3] arr[Symbol.toPrimitive] = arr.shift // arr.shift()会弹出数组的第一个值 arr.toString = arr.pop // [Symbol.toPrimitive] 优先级高于 toString console.log(arr == 1 && arr == 2 && arr == 3) // true -
-
另外的,还可以使用数组自己的方法来转换为字符串
- 使用
join()方法可以拼接字符串,默认分隔符为,,也可自定义分隔符
let arr = ['a','b','c'] arr.join() // a,b,c arr.join('-') // a-b-c - 使用
03. 操作符转换
-
概念:通过操作符的转换,如
A == B、A > B -
规则:
- 除了字符串和对象进行比较的时候,需要把对象转换为字符串进行比较
- 其它的,只要类型不同,都会转换为数值类型进行比较
-
示例:
数字 == 字符串:把字符串转换为数字进行比较数字 == 布尔:把布尔转换为数字进行比较数字 == 对象:把对象转换为字符串类型再转换为数字进行比较字符串 == 布尔:都转换为数字进行比较对象 == 布尔:都转换为数字进行比较对象 == 字符串:那对象转换为字符串进行比较
-
特别的,
null和undefined在与其它数据进行相等判断时,不会进行类型转换-
但在进行关系运算时(大于、小于、...),会进行类型转换
-
null == undefined
-
-
按题理解:分析
[] == ![]-
首先判断类型是否一致
-
左边是
[],对象类型 -
右边是
![],布尔类型,![] == false
类型不一致,都转换为数值类型进行比较
-
-
转换布尔类型的值为Number类型
Number(false) == 0
-
转换对象类型的值为Number类型
- 先转换为字符串:
[].toString == '' - 再把字符串转换为数值:
Number('') == 0
- 先转换为字符串:
-
最后比较
0 == 0- 即最终结果为
true
-
04. 运算符转换
-
只有当加法运算时,其中一方是字符串类型,就会把另一个也转为字符串类型
- 并且加法运算会触发三种类型转换
- 将值转换为原始值
- 转换为数字
- 转换为字符串
- 并且加法运算会触发三种类型转换
-
数字情况
数字+数字=数字
布尔+布尔=数字
数字+布尔=数字
数字+Null=数字
console.log(1 + '1') // 11
console.log(1 + null) // 1
console.log([] + []) // ''
console.log([] + {}) // '[object Object]'
分析一道题:console.log(!+[] + [] + ![])
-
虽然有三个
+符号,不过第一个+之前没有数据- 所以它是数值类型的隐式转换,即:
+[] == 0 - 所以:
!+[] == !0 == true
- 所以它是数值类型的隐式转换,即:
-
那么最后一个
![]是一个布尔类型的值- 根据布尔类型的转换规则,除了那7个值,其它的都转换为
true - 所以这里
![] == !true == false
- 根据布尔类型的转换规则,除了那7个值,其它的都转换为
-
最终的表达式就是:
console.log(true + [] + false)- OK,没有数字类型,结果为字符串,
[] == '' - 所以最终结果是:
'truefalse'
- OK,没有数字类型,结果为字符串,
本人前端小菜鸡,如有不对请谅解