JavaScript 中的强类型转换和隐式类型转换

总结:

Javascript 是一种弱类型语言,这意味着变量是没有明确类型的,而是由 JavaScript 引擎在编译时隐式完成,类型转换是将一种数据类型转换为另一种数据类型。

常见的类型转换有2种:强类型转换和隐式类型转换

① 强类型转换也叫显示类型转换,一般由开发人员手动类型转换,通过 JavaScript 内置的 API ,例如 Number() / toString() / Boolean() 等

② 弱类型转换一般由 JavaScript 编译器完成的自动类型转换,例如在使用算数运算符(加减乘除)或者判断宽松相等时。​​​​​​​

一、隐式类型转换

凡是通过逻辑运算符( &&  ||  ! )、算数运算符(+ - * / )、关系操作符(<  <=  >  >=) 和 == (相等运算符)、if while 条件的操作,如果类型不一样,就会出现隐式类型转换。

1、加号(+)

+号比较特殊,既可以当做算数运算符做加法,又可以当做字符串连接符

 + 的隐式类型转换规则:

① 如果两个是数字,则执行相加;
② 两个都是是字符串,则作为字符串拼接;
③ 一个是字符串,另一个为 undefined、null、布尔型,调用 toString() 进行拼接;

④ 一个为数字,另一个 undefined、null、布尔型或数字,会将其转化为数字进行相加操作;
⑤ 一个字符串,一个数字,作为字符串拼接;
⑥ 一方为数字,一方为 BigInt 类型,不能执行相加,会报type Error错误;

① 算数运算符

除了 string 类型以外的原始数据类型进行加法运算时,非数字类型会转换为数字类型。

进行算术运算时,原始数据类型转为数字,使用 Number() 方法。

console.log(1 + 1) // 2
console.log(1 + undefined) // NaN
console.log(1 + null) // 1
console.log(null + undefined) //  NaN
console.log(true + false) // 1
console.log(true + 1) // 2

② 字符串连接符

当含有string类型和引用数据类型时,+号会作为字符串连接符使用,非string类型会转换为string类型。

引用数据类型:会调用自身 toString 方法,如果返回不是原始值,会继续调用自身 valueOf 方法;

非引用数据类型:v.isString() 如果是true,它将调用v.toString()。否则,它将值转换为字符串

console.log(1 + '2') // '12'
console.log('2' + '2') // '22'
console.log('1' + true) // '1true'
console.log('1' + false) // '1false'
console.log('1' + undefined) // '1undefined'
console.log('1' + null) // '1null'
console.log('1' + NaN) // '1NaN'
console.log('2' + []) // '2'
console.log(2 + [1, 2]) // '21,2'
console.log(2 + { a: 1 }) // '2[object Object]'
console.log([] + {}) // '[object Object]'
console.log({} + []) // '[object Object]'
console.log(3 + {}) // '3[object Object]'
console.log({} + 3) // '[object Object]3'
console.log(true + []) // 'true'
console.log(true + {}) // 'true[object Object]'
console.log(undefined + {}) // 'undefined[object Object]'

比较特殊字符串和 BigInt 相加,BigInt 转换为字符串

'1' + 1n // 11

2、除加号以外的算数运算符(- * /)

非数字类型会转换为数字类型;

原始数据类型:调用 Number() 方法进行转换;

引用数据类型:调用自身 valueOf 方法进行转换,如果转换后不是原始值,则会调用 toString 方法进行转换,如果转换后不是数字,则会调用 Number() 进行转换,如果转换后不是数字则会返回NaN

console.log(10 - 1) // 9
console.log(10 - '1') // 9
console.log(10 - null) // 10
console.log(10 - undefined) // NaN
console.log(10 - NaN) // NaN
console.log(10 - true) // 9
console.log(10 - false) // 10
console.log(10 - {}) // NaN
console.log(10 - {name: '草莓'}) // NaN
console.log(10 - [1,2]) // NaN

3、逻辑运算符(&&   ||  !!!) 

非布尔类型会转换为布尔类型,引用数据类型转换为布尔值后总会是 true

①  !

!a,如果a为布尔值,则直接取反;如果a为非布尔值,则会转换为布尔值然后取反

② &&

a && b,如果a为true,则会返回b;如果a为false,则会返回a

③ ||

a || b,如果a为true,则会返回a;如果a为false,则会返回b

④ !! 

 !!a,会直接将非布尔值转换为布尔类型的值

console.log(![]) // false
console.log(!{}) // false
console.log(!1) // false
console.log(!0) // true
console.log(!undefined) // true
console.log(!null) // true
console.log(!'') // true
console.log(!NaN) // true

console.log(1 && 2) // 2
console.log([] && 2) // 2
console.log(2 && {}) // {}

console.log(2 || {}) // 2 
console.log(false || {}) // {}
console.log('' || {}) // {}

console.log(!!{}) // true
console.log(!![]) // true
console.log(!!0) // false
console.log(!!1) // true
console.log(!!'') // false

4、比较运算符(==  >  < 等) 

1) == 隐式转换规则 

① 判断类型是否相同,类型相同,不进行类型转换,只比较大小;

② 其中一个值为 null 和 undefined,另一个值也必须为 null 或者 undefined,才会返回true;

如果有一个值为Symbol类型,直接返回false

④ 如果两者是 string 和 numbel,将字符串转换为 number;

⑤ 一方为 Boolean,把 Boolean 值转换为 number 再判断;

⑥ 一方为 Object,且另一方为 string、number、symbol,就会把 object 转换为原始类型再进行(调用 object 的 valueOf() 或 toString()方法进行转换) 

2)具体分析:

null 与 undefined 进行 == 比较时,不会进行转换,总返回 true

Javascript 规范中要比较相等性之前,不能将 null 和 undefined 转换成其他任何值,并且规定 null 和 undefined 是相等的

null 和 undefined 都代表无效的值。而且全等于状态下,是false,因为它们不属于同一数据类型。

null 在 == 运算符下,只与 null 和 undefined 相等

console.log(undefined == null) // true
console.log(undefined == '') // false
console.log(null == null) // true
console.log('' == null) // false
console.log(undefined == undefined) // true

NaN 是唯一一个与自身不相等的值;

console.log(NaN == NaN) // false
console.log('' == NaN) // false

基本数据类型,除了 undefined、null、NaN ,其余的一般会先转换为数字类型,再比较是否相等

Number('')为0

console.log('' == '') // true
console.log(1 == '1') // true

如果其中一个是引用数据类型,会先转换为string(先调用valueOf,后调用toString),再转换为number

[ ].valueof()是 [ ]  ,而且 [ ].tostring()是 ' ' ,Number(' ')是0

console.log(0 == []) // true
console.log('' == []) // true
console.log('1,2' == [1,2]) // true

如果==左右都是引用数据类型,会进行地址比较;

因为[ ]属于引用类型,在两个[ ]分别指向不同的堆内存,地址不同;

引用类型数据判断是否相等是判断引用地址是否一致

console.log([] == []) // false
console.log([1, 2] == [1, 2]) // false
console.log({} == []) // false
console.log({} == {}) // false
var a = {
    value: 0,
    valueOf: function() {
        this.value++;
        return this.value;
    }
};
// 注意这里a又可以等于1、2、3
console.log(a == 1 && a == 2 && a ==3); // true
console.log(a)
console.log(a == 3) // false 
console.log(a == 4) // false
console.log(a)
// 看一下 object 隐式转换
// 但是执行过3遍之后,再重新执行 a==3 或之前的数字就是 false,因为 value 已经加上去了(value值每次== 都在向上加)

5、Object 的转换规则

① 如果有 Symbol.toPrimitive 方法,优先调用再返回;

② 调用 valueOf(),如果转换为基础类型,则返回;

③ 调用 toString(),如果转换为基础类型,则返回;

④ 如果都没有返回基础类型,会报错;

Symbol.toPrimitive:如果对象为 Date 对象,转换为基本类型先调动 toString(),后调用 valueOf(),其他都为先调用 valueof(),后调用 toString()

 Symbol.toPrimitive - JavaScript | MDN

Symbol.toPrimitive 是内置的 symbol 属性,其指定了一种接受首选类型并返回对象原始值的表示的方法。它被所有的 强类型转换制 算法优先调用。 

let obj = {
    [Symbol.toPrimitive]() {
        return 200
    },
    valueOf() {
        return 300
    },
    tostring() {
        return 'Hello'
    }
}
console.log(obj + 200) // 400
var obj = {
    value: 1,
    valueOf() {
        return 2;
    },
    toString() {
        return '3'
    },
    [Symbol.toPrimitive]() {
        return 4
    }
}
console.log(obj + 1); // 输出5
// 因为有Symbol.toPrimitive, 就优先执行这个; 
// 如果Symbol.toPrimitive这段代码删掉, 则执行valueOf()打印结果为3;
// 如果valueOf也去掉, 则调用toString返回'31'(字符串拼接)

// 两个特殊的情况:
10 + {}
// "10[object object]"
// 注意: {}会默认调用 valueOf是{},不是基础类型继续转换,调用toString,返回结果"[object object]”,于是和10进行”+”运算,按照字符串拼接规则

[1,2,undefined,4,5] + 10
// "1,2,,4,510”
// 注意[1,2,undefined,4,5] 会默认先调用 valueOf 结果还是这个数组, 不是基础数据类型继续转换,也还是调用toString, 返回“1,2,,4,5”, 然后再和10进行运算, 还是按照字符串拼接规则

二、强类型转换 

强制类型转换的方式包含了:Number()、String()、Boolean()、parselnt()、parseFloat()、toString() 等方法 

1、Number 类型的转换

Number(-0X11); // -17
Number('0X11'); // //17

2、toString 类型的转换

① 基本数据类型 

② 引用数据类型

③ 总结 

3、Boolean 类型的转换

除了 false、0(+0、-0)、NaN、null、undefined、' ',这六种值为 false,其他都为 true 

4、Parselnt() 方法的转换规则

console.log(parseInt('')) // NaN 
// 如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN

console.log(parseInt(true)); // NaN
console.log(parseInt(false)); // NaN
console.log(parseInt('0111')); // 111
console.log(parseInt(null)); // NaN

console.log(parseInt('1lalal')); // 1
console.log(parseInt(-0X11)) // -17
console.log(parseInt('0X11")) // 17

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值