数据类型转换

1.强制类型转换的规则

1.1 数值

数值 转换为数值 转换为字符串 转换为布尔值
0 “0” false
-0 “0” false
1(有限,非0,非NaN数值) “1” true
Infinity “Infinity” true
-Infinity “-Infinity” true
NaN “NaN” false

1.2 字符串

字符串 转换为数值 转换为字符串 转换为布尔值
“” (空字符串) 0 false
“1.2” (非空,数值字符串) 1.2 true
“one” (非空,非数值字符串) NaN true

1.3布尔值

布尔值 转换为数值 转换为字符串 转换为布尔值
true 1 “true”
false 0 “false”

1.4 null和undefined

null和undefined 转换为数值 转换为字符串 转换为布尔值
undefined NaN “undefined” false
null 0 “null” false

1.5 符号

符号 转换为数值 转换为字符串 转换为布尔值
Symbol(“Danny”) (任意符号) 不能转换 ‘Symbol(“Danny”)’ true

1.6 大整型

大整型 转换为数值 转换为字符串 转换为布尔值
123n (任意大整型) 123 “123” true

1.7 对象

对象 转换为数值 转换为字符串 转换为布尔值
{} (任意对象) NaN 或 依据对象的valueOf()方法 “[object Object]” 或依据对象的toString()方法 true

1.8 数组

数组 转换为数值 转换为字符串 转换为布尔值
[] (空数组) 0 “” (空字符串) true
[9] (仅含1个数值元素的数组) 9 “9” true
[xxx, xxx] (其它任何数组) NaN join(",")方法转换 true

1.9 函数

函数 转换为数值 转换为字符串 转换为布尔值
任何函数 NaN 返回函数代码的字符串形式,原生方法会显示Native Code true

2.显示转换与隐式转换

2.1 隐式转换

在JavaScript权威指南中提供了一些隐式转换的例子一般发生在“+,-,*,/,==,>,<,!=,>=,<=,!!”11个操作符和函数参数之中,可以把隐式转换理解为不调用类型转换函数的转换方法。

  1. +或-作为二元操作符:

    • 当两边存在字符串时,另一边会隐式转化为字符串
    • 其它情况会转化为数值
  2. +或-作为一元操作符:

    • 表示正数,会转化为数值
  3. *或/作为二元操作符:

    • 表示乘除运算,会转化为数值
  4. ==和!=作为二元操作符:

    • 表示宽松地相等判断,会转化为数值
    • 底层实现上,null和非0进行宽松相等判断时,不会转化为数值。null和undefined宽松相等。
  5. >和<和<=和>=作为二元操作符:

    • 只有在都是字符串的情况下进行字符串字典序比较
    • 如果两边不都是字符串,会转化为数值
  6. !!作为一元操作符:

    • !表示将x转化为布尔值后取反,!!表示获取x的布尔值

2.2 显式转换

显示转换可以理解为调用类型转换函数的转换方法。

  1. 工厂函数转化方法:调用Number(x),String(x),Boolean(x),BigInt(x),Symbol(x),Object(x)等工厂函数对x进行类型转换。原始类型的工厂函数返回原始类型。

  2. 构造函数转化方法:调用new Number(x),new String(x),new Boolean(x),new BigInt(x),new Object(x)等构造函数对x进行类型转换。原始类型的构造函数返回一个对象。

  3. 数值和字符串的转化:(最常用的4个API)

    • 数值到字符串toString(num):在这种情况下toString()接收一个可选参数,表示转化后的进制
    • 数值到字符串toFixed(num):在这种情况下toFixed()接收一个可选参数,表示转化后保留几位小数
    • 字符串到数值parseInt(string, num):(1)parseInt接收两个参数,一个是字符串,另一个表示转换时的进制;(2)会根据字符串开头的0x,0b来判断转换后是几进制。
    • 字符串到数值parseFloat(string):parseFloat接收一个参数,为字符串

3.对象到原始值的转换

注: Object基类有toString和valueOf方法,分别返回“[object Object]”和{}

3.1 对象到原始值的显示转换

对象的显式转换应用在调用显示转换函数之中,例如原始类型的工厂函数。

  1. 数值转化:(同偏数值算法)

    • 调用valueOf(),如果返回值不是引用类型,那么直接返回,否则下一步
    • 调用toString(),如果返回值不是引用类型,那么直接返回,否则下一步
    • 抛出TypeError错误,不可转化
  2. 字符串转化:(同偏字符串算法)

    • 调用toString(),如果返回值不是引用类型,那么直接返回,否则下一步
    • 调用valueOf(),如果返回值不是引用类型,那么直接返回,否则下一步
    • 抛出TypeError错误,不可转化
// 对象的显示类型转化的测试,符合上述算法
class Test {
    toString() {
        console.log("调用了toString")
        return "123"
    }
    valueOf() {
        console.log("调用了valueOf")
        return {
            name: "Danny"
        }
    }
}
let test = new Test
console.log(Number(test))
// 调用了valueOf
// 调用了toString
// 123
console.log(String(test))
// 调用了toString
// 123

3.2 对象到原始值的隐式转换与偏好算法

偏好算法应用于对象到原始值的隐式转化,即上述提到的11种操作符运算和函数参数之中。在JavaScript除了Date对象,其它对象都是偏数值算法进行转化。

  1. 偏数值算法:
    • 调用valueOf(),如果返回值不是引用类型,那么直接返回,否则下一步
    • 调用toString(),如果返回值不是引用类型,那么直接返回,否则下一步
    • 抛出TypeError错误,不可转化
// JavaScript除了Date对象,默认都是偏数值算法,会先调用valueOf。
class Test {
    toString() {
        console.log("调用了toString")
        return "123"
    }
    valueOf() {
        console.log("调用了valueOf")
        return {
            name: "Danny"
        }
    }
}
let test = new Test
console.log(test == "Danny")
// 调用了valueOf
// 调用了toString
// false
  1. 偏字符串算法:
    • 调用toString(),如果返回值不是引用类型,那么直接返回,否则下一步
    • 调用valueOf(),如果返回值不是引用类型,那么直接返回,否则下一步
    • 抛出TypeError错误,不可转化
// JavaScript的Date对象是偏字符串算法,会优先调用toString。
Date.prototype.toString = function() {
    console.log("调用了toString")
    return {
        name: "Danny"
    }
}

Date.prototype.valueOf = function() {
    console.log("调用了valueOf")
    return 123
}

let date = new Date

console.log(date == 123)
// 调用了toString
// 调用了valueOf
// true
  1. 无偏好算法: 在对象的隐式类型转化中,不偏向任何一方,由自己定义偏好,可以通过[Symbol.toPrimitive] (hint)来定义偏好。
// 自定义一个偏字符串算法的类,由输出结果可知,并没有调用传统的toString和valueOf方法
class Test {
    [Symbol.toPrimitive](hint) {
        if(hint === "number") {
            console.log("Symbol.toPrimitive的number")
            return 10
        }
        if(hint === "string") {
            console.log("Symbol.toPrimitive的string")
            return "Danny"
        }
        else if(hint === "default") {
            // 设置成偏字符算法
            console.log("Symbol.toPrimitive的default")
            return "Danny"
        }
    }
}
let test = new Test
console.log(test == "Danny")
// Symbol.toPrimitive的default
// true

console.log(test + 1)
// Symbol.toPrimitive的default
// Danny1

4.真值和假值

4.1 真值和假值的理解

在JavaScript中真值,假值与布尔值并不是一回事,布尔值是真值和假值的子集。真值和假值主要应用于逻辑运算符,逻辑运算符&&和||的两侧的结果就是真值和假值。

4.2 真值和假值的类型

  1. 假值:(3个数值+null与undefined+1个字符串)

    • 0
    • -0
    • NaN
    • undefined
    • null
    • “”
  2. 真值:

    • 除了上述6个假值,其余都是真值

5.宽松相等与严格相等

5.1判断相等的区别

宽松相等==:

  1. 原始类型之间判断: 做隐式类型转换,尽可能转换成数值。
    注:null在和非0的原始类型比较时,null不会隐式转换为数值

  2. 原始类型与对象之间判断: 按照对象的偏好算法做隐式类型转换,之后两者再尽可能转换成数值做比较

  3. 对象之间判断: 对象如果是同一个堆内存则返回true,否则返回false

严格相等===:

  1. 原始类型之间判断: 不做类型转换,如果类型不同返回false,如果相同类型下相同才返回true

  2. 原始类型与对象之间判断: 直接返回false

  3. 对象之间判断: 对象如果是同一个堆内存则返回true,否则返回false

6.null和undefined的理解

  1. (数据类型) null和undefined都是原始数据类型,这两个原始类型下各自只有一个值是null和undefined

  2. (保留字) null是JavaScript保留字,undefined不是保留字,是一个全局常量,类似的还有Infinity,NaN等,因此undefined可以用作变量名。可以通过void 0来获取安全的undefined值。

  3. (含义) null表示一个空对象,只有栈内存没有堆内存。undefined表示已经声明但是没有赋值,表示一个变量此时还没有赋予它栈内存。

  4. (存储方式) 第一版JavaScript规定了存储数据的第三位用于类型判断,对象第三位是000,null是所有二进制位都是0,因此在typeof判断时会被误判为对象。undefined是表示-2^30,typeof时会返回”undefined”。

  5. (相等性) 使用==判断null和undefined时返回true,使用严格相等===判断null和undefined时返回false。

你可能感兴趣的:(JavaScript,javascript,数据类型)