js隐式类型转换详解,看这篇文章就够了!

1、隐式转换

++我们知道js式弱类型语言,这意味着当操作涉及不匹配的类型,它将允许隐式类型转换,而不是抛出一个错误。++

原始值转换会在 toString() 方法之前调用 valueOf() 方法,这与强制数字类型转换的行为相似,但与强制字符串类型转换不同。

1、Symbol.toPrimitive

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

Symbol.toPrimitive 属性(用作函数值)的帮助下,对象可以转换为一个原始值。该函数被调用时,会被传递一个字符串参数 hint,表示要转换到的原始值的预期类型。hint 参数的取值是 "number""string""default" 中的任意一个。

对于hint==='default'发生类型转换的情况如下:

  • Date() 构造函数,当它收到一个不是 Date 实例的参数时------字符串表示日期字符串,而数值表示时间戳。
  • + 运算符------如果运算对象是字符串,执行字符串串联;否则,执行数值相加。
  • == 运算符------如果一个运算对象是原始值,而另一个运算对象是对象(object),则该对象将转换为没有首选类型的原始值。

如果值已经是原始值,则此操作不会进行任何转换。对象按以下顺序调用它的 [@@toPrimitive]()(将 hint 作为 default)、valueOf()toString() 方法,将其转换为原始值。

对于hint==='number'则执行强制数字类型转换算法

对于数字类型有两类:number和BigInt

  • number强转,执行Number()
    *

对于hint==='string'用于强制字符串类型转换算法

  • 使用String()强转

:::tip

[Symbol.toPrimitive](hint)由引擎调用,那什么时候hintnumberstringdefault

js 复制代码
const object1 = {
  [Symbol.toPrimitive](hint) {
      console.log(hint)
  },
};
// 当执行 +object1    hint = number
// 当执行 `${obj2}`   hint = string
// 其余情况 hint=default

:::

2.隐式转换示例

js 复制代码
console.log({} + []); // "[object Object]"

{}[] 都没有 [@@toPrimitive]() 方法。因此会调用valueOf方法,而valuieOf返回对象自身,由于返回值还是对象,因此继续调用toString方法,{}.toString()返回"[object Object]"[].toString()返回是空字符串

js 复制代码
{} + {} 
//NAN
({} + {})
'[object Object][object Object]'

第一次看到这个结果我懵了,想不到原因,最后查看资料,发现JavaScript 把第一个 {} 解释成了一个空的代码块(code block)并忽略了它。 NaN 其实是表达式 +{} 计算的结果 (+ 加号以及第二个 {})。 你在这里看到的 + 加号并不是运算符「加法」,而是一个一元运算符,作用是将它后面的操作数转换成数字,和 Number() 函数完全一样。为什么第一个 {} 会被解析成代码块(code block)呢? 因为整个输入被解析成了一个语句:如果左大括号出现在一条语句的开头,则这个左大括号会被解析成一个代码块的开始。

js 复制代码
{} + []
0
/*转换流程如下
+[]
[].valueOf()//不是原始值
[].toString()
Number([].toString())  
Number("")
0
*/
js 复制代码
[1,2]+[3,4]
//'1,23,4'
//[1,2].toString()+[3,4].toString() = '1,2'+'3,4'

3.Number强制类型转换

Number()操作如下:

  • Number 将按原样返回

  • undefined 转换为 NaN。

  • null 转换为 0。

  • true 转换为 1;false 转换为 0。

  • 字符串将被假定为包含数字字面量,并通过解析它们来转换。解析失败会得到 NaN。与实际数字字面量相比,它们有一些细微的差别:

    • 前导和尾随的空格/换行符会被忽略。

    • 前导的数字 0 不会导致该数值成为八进制字面量(或在严格模式下被拒绝)。

      • -允许出现在字符串的开头以指示其符号。(在实际代码中,它们"看起来像"文字的一部分,但实际上是独立的一元运算符。)然而,该标志只能出现一次,并且后面不能跟空格。
      • Infinity 和 -Infinity 被当作是字面量。在实际代码中,它们是全局变量。空字符串或仅包含空格的字符串转换为 0。不允许使用数字分隔符。
  • Symbol 抛出 TypeError

  • 对象首先通过按顺序调用它们的 [@@toPrimitive]()(使用 "number" 提示)、valueOf()toString() 方法将其转换为原始值。然后将得到的原始值转换为数字。

4.String强转规则

  • 字符串按原样返回。
  • undefined 转换成 "undefined"。
  • null 转换成 "null"。
  • true 转换成 "true";false 转换成 "false"。
  • 使用与 toString(10) 相同的算法转换数字。
  • 使用与 toString(10) 相同的算法转换 BigInt。
  • Symbol 抛出 TypeError。
  • 对于对象,首先,通过依次调用其 @@toPrimitive(hint 为 "string")、toString() 和 valueOf() 方法将其转换为原始值。然后将生成的原始值转换为一个字符串。

5.强制类型转换遵循的规则总结

在所有情况下,++[@@toPrimitive]() 如果存在,必须可调用并返回原始值++ ,否则报错TypeError

6.Object.is

Object.is() 确定两个值是否为相同值。如果以下其中一项成立,则两个值相同:

  • 都是 undefined
  • 都是 null
  • 都是 true 或者都是 false
  • 都是长度相同、字符相同、顺序相同的字符串
  • 都是相同的对象(意味着两个值都引用了内存中的同一对象)
  • 都是 BigInt 且具有相同的数值
  • 都是 symbol 且引用相同的 symbol 值
  • 都是数字且
    • 都是 +0
    • 都是 -0
    • 都是 NaN
    • 都有相同的值,非零且都不是 NaN
相关推荐
万少2 小时前
用腻了 WorkBuddy 的默认界面?这个开源小工具给它换上了毛玻璃
前端·javascript·后端
To_OC3 小时前
LC 15 三数之和:双指针不难,难的是把去重做对
javascript·算法·leetcode
触底反弹4 小时前
🔥 前端也能玩转 AI 流式输出!从二进制流到打字机效果,一篇讲透
javascript·人工智能·node.js
胡萝卜术4 小时前
深度重构:Agent Skills——从 Prompt 工程到能力工程
javascript·架构·github
benchmark_cc5 小时前
如何用 Python + QuantDash 快速构建高胜率“配对交易(Pairs Trading)”策略?
开发语言·人工智能·python·pandas·量化交易·quantdash
程序员无隅6 小时前
Coding Agent 为什么压缩上下文后还能继续工作?上下文模块设计拆解
java·开发语言·数据库
Python+996 小时前
Java 枚举类(Enum)详解:从基础到高级应用
java·开发语言·python
二炮手亮子6 小时前
浅记java线程池
java·开发语言
To_OC6 小时前
从 “卡死半天” 到 “打字机效果”:大模型流式输出前端实现全记录
前端·javascript·llm
rockey6277 小时前
基于AScript的JavaScript脚本语言发布啦
javascript·c#·.net·js·script