【JavaScript】04. 类型转换(2)

122 阅读5分钟

这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战

类型转换(2)

01. 对象的转换

  • 在没有toString()方法和valueOf()方法的情况下

    • 对象转换为字符串,会返回[object Object]
    • 对象转换为数值,会返回NaN

  • 如果有相应的方法,那么,对象在转换为基本类型时,可以调用valueOf方法或者toString方法来进行转换,具体步骤如下:

    1. 如果有valueOf()方法

      • 如果它返回一个基本类型值(原始类型值),则会直接返回

      • 如果返回的不是一个基本类型值,则调用toString()方法

    2. 如果没有valueOf()方法

      • 则会调用toString()方法
    3. 如果有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

    • 如果只有一个值:则转换为对应字符串,转换为数值型按数值类型转换规则

    • 如果有多个值:可以转换为字符串,但无法转换为数值类型

    但也可以重写其toStringtoPrimitive方法(通过直接赋值的方法改变)

    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 == BA > B

  • 规则:

    • 除了字符串和对象进行比较的时候,需要把对象转换为字符串进行比较
    • 其它的,只要类型不同都会转换为数值类型进行比较
  • 示例:

    • 数字 == 字符串:把字符串转换为数字进行比较
    • 数字 == 布尔:把布尔转换为数字进行比较
    • 数字 == 对象:把对象转换为字符串类型再转换为数字进行比较
    • 字符串 == 布尔:都转换为数字进行比较
    • 对象 == 布尔:都转换为数字进行比较
    • 对象 == 字符串:那对象转换为字符串进行比较
  • 特别的,nullundefined在与其它数据进行相等判断时,不会进行类型转换

    • 但在进行关系运算时(大于、小于、...),会进行类型转换

    • null == undefined

  • 按题理解:分析[] == ![]

    1. 首先判断类型是否一致

      • 左边是[],对象类型

      • 右边是![],布尔类型,![] == false

      类型不一致,都转换为数值类型进行比较

    2. 转换布尔类型的值为Number类型

      • Number(false) == 0
    3. 转换对象类型的值为Number类型

      • 先转换为字符串:[].toString == ''
      • 再把字符串转换为数值:Number('') == 0
    4. 最后比较

      • 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
  • 最终的表达式就是:console.log(true + [] + false)

    • OK,没有数字类型,结果为字符串,[] == ''
    • 所以最终结果是:'truefalse'

本人前端小菜鸡,如有不对请谅解