彻底弄懂JS隐式转换

一、什么是隐式转换?

定义:由编译器自动完成类型转换的方式就称为隐式转换。

二、转换规则

2.1 基本数据类型

2.1.1将值转为字符串

字符串连接符+ 使用这一规则。(只要+两边出现了字符串就是字符串连接符。
编译器将非string类型的值转为string类型,然后再将其拼接成一个新的字符串。

const test = 1 + '0' + true + undefined + null;
console.log(test); // 10trueundefinednull
console.log(typeof test); // string

2.1.2将值转为数字(Number()函数)

自增/自减运算符,算数运算符,关系运算符使用这一规则。
下表列出将其他类型的值转换为数字的情况:

序号其他类型转换为number类型后的值
1undefinedNaN
2null0
3booleantrue转为1,false转为0
4stringleft-aligned 空字符串''""转为0,123转为数值123,helloa123转为NaN

这里对关系运算符中的几种情况进行说明:
(1)字符串与字符串比较

比较方法(> < >= <= !=):通过依次比较字符串中每个字符所对应的unicode的值,若比较过程中能得出结果,直接返回结果并且不再比较后面的字符。
通过字符串的charCodeAt()方法可以查看每个字符的unicode。
该方法的用法及细节请参考链接: MDN > String.prototype.charCodeAt()

  • 例1
console.log('a2c' > 'ab3'); // false
// 分析
console.log('a2c'.charCodeAt()); // 97
console.log('ab3'.charCodeAt()); // 97
// 不能得出结果,继续比较
console.log('a2c'.charCodeAt(1)); // 50
console.log('ab3'.charCodeAt(1)); // 98
// 得出结果不再比较
  • 例2
// 字符串比较1
console.log('bA'>'b'); // true
// 字符串比较2
console.log('bA'<'b'); // false

// 分析
console.log('bA'.charCodeAt()); // 98
console.log('b'.charCodeAt()); // 98
// 不能得出结果
console.log('bA'.charCodeAt(1)); // 65
console.log('b'.charCodeAt(1)); // NaN
console.log('b'.charCodeAt()); // 98

这里可以看出,当比较的字符串长度不同,并且公共长度的字符比较不能得出结果时,比较的是字符串的长度,来得出结果的。(个人推测,若观点有误,请指正!)

比较方法(==):只有两个相同的字符串比较才为true。

(2)null 与undefined

序号关系式结果
1undefined == undefined ;true
2null== null;true
3undefined == null;true

Javascript规范中:规定nullundefined 是相等的。nullundefined都代表着无效的值。

(3)NaN
NaN代表非数值的特殊值,用于指示某个值不是数字。NaN与任何类型的值比较都是false。

2.1.3将值转为布尔值(Boolean()函数)

逻辑非运算符!使用这一规则。编译器通过Boolean()函数将非布尔类型的值转为布尔值。
下表列出只需记住以下转为布尔值为false的5种情况即可,其余全为true

序号备注
1undefinedundefined 类型
2nullnull 类型
30number 类型
4NaNnumber 类型
5空字符串:双引号""或单引号''空格' '" "为true

2.2 引用数据类型

2.2.1 引用数据类型互相比较

比较的是引用数据类型指向的地址。

console.log([] == []);// false:两个空数组指向不同的地址

const a = [];
const b = a;
console.log(a == b); // true:数组a, 数组b指向相同的地址

2.2.2 引用数据类型与基本数据类型比较

引用数据类型都是object实例,都会继承object的方法,所以都有valueOf()toString()方法。
转换规则:先使用valueOf()获取原始值,如果原始值不是number类型,使用toString()转换为string类型,再转换为number类型比较或计算。

引用数据类型的valueOf()转换

引用数据类型使用valueOf()转换成原始值
Numbernumber类型。转换的值参考本文2.1.2将值转为数字
Stringstring类型。转换为字符串。
Booleanboolean类型。转换的值参考本文2.1.3将值转为布尔值
Datenumber类型。转换为从 1970 年 1 月 1 日午夜开始计算的毫秒数。
Array, Math,RegExp, Function,Objectthis,对象本身

常见内置对象的toString()转换规则

常见内置对象使用toString()转换成字符串
Array数组元素以逗号隔开的字符串
Function函数源代码的字符串
Object[object Object]
Math[object Math]
RegExp正则表达式的字符串值

常见内置对象的toString()转换测试

console.log([1, 2, 3, 4].toString()); // 1,2,3,4
console.log({ age: 18 }.toString()); // [object Object]
function func() { }
console.log(func.toString()); // function func() { }
console.log(Math.toString()); // [object Math]
const exp = new RegExp(',');
console.log(exp.toString()); // /,/

2.3 特殊1:逻辑非与关系运算符同时出现

逻辑非!的优先级高于关系运算符,所以优先转换为boolean类型,再进行关系比较。
例题:

console.log([] == !{}); // true
  • 过程分析:
    • 运算优先级:! > ==!{}false, 等式变为 [] == false
    • []通过valueOf()转换为[]=>通过toString()转换为'',等式变为'' == false
    • 将其转换为number类型,即:0 == 0,等式成立,结果为true

2.4特殊2:+陷阱

2.4.1字符串连接符(有时会被浏览器认为一元+运算)

(1)字符串与其他类型拼接不再赘述。
(2)在浏览器的控制台中直接打印:空对象+其他数据类型时

空对象 + 任意对象(不同浏览器出现不同结果)

  • Chrome
    • 每个{}都会按照valueOf -> toString的转换顺序变为字符串的[object Object]
    • +两边出现了字符串,即为字符串拼接符。即:{} + {} -> '[object Object]' + '[object Object]' = '[object Object][object Object]'
    • Chrome
  • FireFox
    • 浏览器会将{}认为是一个空的代码区块(而不是一个对象字面量)并忽略,即:+{}
    • 一元+会触发强制类型转换。即:{} + {} -> +{} -> Number({}) = NaN
    • FireFox

空对象 + 其他数据类型(对象类型除外)

这次所有的浏览器都会将{}认为是一个空的代码区块,即使用一元+将其他类型转换为number类型的值。

ChromeChrome
FireFox
FireFox

2.4.2加法运算

除string类型与引用数据类型之外的原始类型的才是加法运算
核心:将其他原始类型转换为number类型

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

总结

JS隐式转换规则以流程图形式呈现(字符串拼接符的隐式转换除外)
JS隐式转换规则流程图

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值