JavaScript类型转换

223 阅读5分钟

1. == 操作符的强制类型转换规则?

对于 == 来说,如果对比双方的类型不一样,就会进行类型转换。假如对比 xy 是否相同,就会进行如下判断流程:

  1. 判断两者类型是否相同,相同的话就比较两者的大小;
  2. 类型不相同的话,就会进行类型转换;
  3. 判断是否在对比 nullundefined,是的话就会返回 true
  4. 判断两者类型是否为 stringnumber,是的话就会将字符串转换为 number
  5. 判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断;
  6. 判断其中一方是否为 object 且另一方为 stringnumber 或者 symbol,是的话就会把 object 转为原始类型再进行判断;

2. 其他值到字符串的转换规则

  • Boolean 类型,true 转换为 "true"false 转换为 "false"
  • Number 类型的值直接转换,不过那些极小和极大的数字会使用指数形式。
let a = 2012312312312321313213123;
let b = 123432
console.log(a.toString()) // '2.0123123123123213e+24'
console.log(b.toString()) // '123432'
  • NullUndefined 类型 ,null 转换为 "null"undefined 转换为 "undefined"
  • BigInt 类型的值直接转换,不过会去掉最后的'n'
let a = 2012312312312321313213123n
console.log(a.toString()) // '2012312312312321313213123'
  • Symbol 类型的值直接转换,但是只允许显式强制类型转换,使用隐式强制类型转换会产生错误。
let b = Symbol('name')
let c = Symbol('name')
console.log(b.toString()) // 'Symbol(name)'
console.log(c.toString()) // 'Symbol(name)'
  • 对普通对象来说,除非自行定义 toString() 方法,否则会调用 toString()Object.prototype.toString())来返回内部属性 [[Class]] 的值,如"[object Object]"。如果对象有自己的 toString() 方法,字符串化时就会调用该方法并使用其返回值。 例如:
[1,2,3].toString() // '1,2,3'
Object.prototype.toString.call([1,2,3]) // '[object Array]'

3. 其他值到数字值的转换规则?

  • Undefined 类型的值转换为 NaN
  • Null 类型的值转换为 0
  • Boolean 类型的值,true 转换为 1false 转换为 0
  • String 类型的值转换如同使用 Number() 函数进行转换,如果包含非数字值则转换为 NaN,空字符串为 0
  • Symbol 类型的值不能转换为数字,会报错。
  • 对象(包括数组)会首先被转换为相应的基本类型值,如果返回的是非数字的基本类型值,则再遵循以上规则将其强制转换为数字。
let num1 = undefined
let num2 = null
let num3 = true
let num4 = false
let num5 = '123'
let num6 = '123a'
let num7 = Symbol('num')
console.log(Number(num1)) // NaN
console.log(Number(num2)) // 0
console.log(Number(num3)) // 1
console.log(Number(num4)) // 0
console.log(Number(num5)) // 123
console.log(Number(num6)) // NaN
console.log(Number(num7)) // 报错:Cannot convert a Symbol value to a number

4. object 类型值转为原始类型值

4-1. 转换算法

3种转换算法:偏字符串算法、偏数值算法、无偏算法

4-1-1. 偏字符串算法

首先尝试使用 XX.toString() 方法,如果 XX.toSting() 方法不存在或者返回值不是一个原始类型的值,则尝试使用 XX.valueOf() 方法,如果 XX.valueOf() 仍然无法返回一个原始类型的值,则转换失败,报 TypeError

4-1-2. 偏数值算法

偏数值算法与偏字符串算法类似,只不过偏数值算法会先尝试XX.valueOf()方法,再尝试 XX.toString() 方法。

4-1-3. 无偏算法

取决于被转换的对象。如果是一个 Date 对象,则使用偏字符串算法,否则使用偏数值算法。

4-2. XX.tostring()XX.valueOf()

4-2-1. XX.tostring()

XX.tostring()任务是返回对象的字符串表示。

  1. 普通对象:返回"[object object]"
  2. Array 类:将每个元素转换为字符串,再用逗号作为分隔符将它们拼接起来。
  3. Function 类:返回 JavaScript 源码的字符串。
  4. Date 类:返回一个人类友好(且 JavaScript 可解析)的日期和时间字符串。
  5. RegExp:返回一个看起来像 RegExp 字面量的字符串。

4-2-2. XX.valueOf()

把对象转换为可以代表对象的原始类型的值。

  1. 默认情况下,XX.valueOf() 返回对象本身;
  2. BooleanStringNumber 这样的包装类定义的 valueOf() 方法返回被包装的原始值。
  3. Date 类的实例上的 valueOf() 方法返回日期的内部表示形式,即:自1970年1月1日至今的毫秒数。

4-3. 转换算法的使用场景

  1. + 操作符:如果有一个参数是字符串,则把另一个原始值也转换成字符串,然后进行字符串拼接;否则将两个参数都转换成数值并把它们相加。
  2. ==!=:如果一个数值是对象,另一个操作数是原始值,则使用无偏好算法将对象转换为原始值,再进行后续比较。
  3. <<=>>=:如果操作数中有一个值是对象,则使用偏数值算法将对象转换成原始值。注意:这个偏数值算法得到的原始值不会再被转换成数值。

5. JavaScript 中如何进行隐式类型转换

在对象转换成基本类型数据时,Date类对象使用偏字符串算法,其他对象使用偏数值算法

而 JavaScript 中的隐式类型转换主要发生在+、-、*、/以及==、>、<这些运算符之间。而这些运算符只能操作基本类型值,所以在进行这些运算前的第一步就是将两边的值转换成基本类型,再进行操作。

以下是基本类型的值在不同操作符的情况下隐式转换的规则:

  1. + 操作符:+ 操作符的两边有至少一个string类型变量时,两边的变量都会被隐式转换为字符串;其他情况下两边的变量都会被转换为数字。

  2. -、*、\ 操作符:两边先转换为数字再计算( NaN也是一个数字)

  3. == 操作符:操作符两边的值都尽量转成number

  4. <> :如果两边都是字符串,则比较字母表顺序;其他情况下,转换为数字再比较。