JS中的隐式类型转换规则

简介: JavaScript 是一门弱类型语言,变量类型在运行时会进行隐式转换。本文总结了常见的隐式转换规则,包括运算符转换、等号比较和布尔值转换等。例如,`1 + {a: 1}` 会先调用对象的 `toString()` 方法,最终结果为 `'1[object Object]'`。此外,还详细解析了 `undefined` 和 `null` 的运算行为,以及 `![] == []` 等特殊情况。通过这些例子,帮助开发者更好地理解 JavaScript 中的类型转换机制。

前言

JavaScript作为一门弱类型语言,并不像C、Java那样有明确的类型定义如int、boolean、string、float、double等数据类型,而js同时又是一门脚本语言,逐行编译运行的,为了防止运行出错,就存在了变量类型的隐式转换

本人使用js也有一段时间了,但是对这个转换规则还是有点不理解全面,所以从网上学习回来,总结了这个隐式转换规则,从此以后不再纠结于这个东西,请往下看

转换规则

运算符的转换规则

  • -左右两边的值会被转换成number再进行运算(* % / 也类似)
  • +左右两边的值如果都为number,则进行正常的数值相加,否则判定为字符串拼接,将两个值转换为string后进行拼接
  • 如果是存在复杂类型运算,会先将复杂类型转换为原始类型(Primitive),再进行运算,转换的过程如下:
    先调用复杂类型对象上的valueOf()方法,如果返回值的不是原始类型,则调用toString()方法
  • undefinde或null与非string类型的原始类型相加时,先将两边转换为number类型,所以总是会等于NaN
  • undefinde或null与string类型,将前者转换为string类型进行字符串拼接

等号(==)两边对比的转换规则

  • !后面的值会直接转换成boolean
  • 对于原始类型之间的比较(==),如果两边类型一致,则直接进行比较,否则会先都转换为number类型,再进行比较
  • 对于复杂类型与原始类型之间的运算,
  • 复杂类型与复杂类型之间的比较,则是比较其内存地址是否相等
  • 还有一种特殊情况就是undefined和null,undefined == null 永远为true,undefined和null与其他类型的值进行比较时永远为false
    下面是在网上偷的一张图片,能够很好解释不同类型之间比较时的类型转换:

非布尔值转换为布尔值

ECMA规范:

非布尔类型转换为布尔类型时:

长度为0的字符串、undefined、null、0、±0、NaN会转换为false

非0且不为NaN的number类型、长度大于0的字符串、复杂类型会转换为true

例子解析

1+{a:1}

js

代码解读

复制代码

console.log(1+{a:1}) // '1[object Object]'

{a:1}是object类型,会先调用valueOf()方法,依旧返回{a:1},不为原始类型,则调用toString()方法,返回'[object Object]',为string类型,ok,进行字符串拼接,得到上面的结果

为了验证是不是这个过程,我们先重写toString方法,使其返回'{a:1}'

结果如下:

继续改写valueOf()方法,使其返回1

结果如下:

看来确实是这样的转换过程

undefined和null与其他类型的+运算

js

代码解读

复制代码

console.log(undefined+1)  // undefined + 1 -> NaN + 1 = NaNNaN
console.log(undefined+'1') // undefined + '1' -> 'undefined' + '1' = 'undefined1'
console.log(null+1)  // null + 1 -> 0 + 1 =1
console.log(null+'1')  // null + '1' -> 'null' + '1' = 'null1'
console.log(null+undefined)  // null + undefined -> 0 + NaN = NaN
console.log(undefined+[1,2])  // undefined + [1,2] -> 'undefined' + '1,2' = 'undefinde1,2'
console.log(null+[1,2])   // null + [1,2] -> 'null' + '1,2' = 'null1,2'

![] == []

js

代码解读

复制代码

console.log(![] == []) // true

首先,等式左边为![],存在!,将[]直接转换为boolean类型,![] -> !true = false

所以 (![] == []) -> (false == []) -> (0 == 0) = true

1+{} 与 {}+1

js

代码解读

复制代码

{}+1 // 1
1+{} // '1[object Object]'

一开始以为 {}+1 的值会是 '[object Object]1',结果却是1,其实并不是转换的问题,而是{}的问题,解释如下:

1+{},因为+在前,所以{}被当成运算符,它的值是'[object Object]',所以整个运算会自动类型转换 {}+1,{}在前,整个语句并没有被解析成一个表达式,被分开执行,就变成了:

js

代码解读

复制代码

{
};
+1

于是真正的语句就变成了+1,结果就是1了

只要加个小括号,就能去除二义性了

js

代码解读

复制代码

({})+1)


转载来源:https://juejin.cn/post/7147221430852124703

相关文章
|
3月前
|
JavaScript 前端开发 安全
如何处理 JavaScript 中的类型转换错误?
【10月更文挑战第9天】处理类型转换错误需要综合运用多种方法和策略,同时要保持对潜在问题的警惕性。通过合理的错误处理,可以提高程序的健壮性,减少因类型转换错误带来的负面影响。
40 0
|
3月前
|
JavaScript 前端开发
JS隐式类型转换规则
【10月更文挑战第9天】 不同的 JavaScript 引擎可能在隐式类型转换的具体实现上存在一些细微差别。理解这些隐式类型转换规则对于正确处理数据和避免错误非常重要。
22 0
|
4月前
|
JavaScript 前端开发
JavaScript 类型转换
JavaScript 类型转换
28 4
|
5月前
|
JavaScript 前端开发
JavaScript的命名规则
JavaScript的命名规则
137 0
|
5月前
|
JavaScript 前端开发
js中的命名规则
js中的命名规则
|
5月前
|
JavaScript 前端开发
JS:类型转换(四)从底层逻辑让你搞懂经典面试问题 [ ] == ![ ] ?
JS:类型转换(四)从底层逻辑让你搞懂经典面试问题 [ ] == ![ ] ?
|
7月前
|
JavaScript 前端开发
JavaScript变量命名规则及关键字详解
JavaScript变量命名规则及关键字详解
106 1
|
6月前
|
JavaScript
js【详解】自动类型转换
js【详解】自动类型转换
28 0
|
6月前
|
JavaScript 前端开发
|
8月前
|
JavaScript
js的一些运算符规则
js的一些运算符规则
44 1