首页 > 编程语言 >神奇的JavaScript弱等价类型转换

神奇的JavaScript弱等价类型转换

时间:2024-06-11 20:34:03浏览次数:16  
标签:类型转换 转换 数字 JavaScript 等价 value 类型 true

JavaScript语言特性 - 类型转换

JavaScript这门语言的类型系统从来没有它表面看起来的那样和善,虽然比起Java、C#等一众强类型语言,它的弱类型使用起来似乎是如此便利,但正因为它极高的自由度,所以才会衍生出令人摸不着头脑的荒诞行为。
举个例子,虽然我们都知道一个包含内容的字符串会被认为是“真值 Truthy”(因为除了空字符串之外任何字符串在JS里都被认为真值),但当你做如下比较的时候,你会得到一个惊掉下巴的结果

const a = "18";
const b = true;

a == b  // false

什么鬼,一个被通常理解成真值的值,竟然无法与布尔真值松散相等?
为了能拨开JavaScript类型的迷雾,让头铁的我们一点一点理顺JavaScript整个类型系统的工作逻辑。

读者可以根据自己对JS类型系统的掌握程度,选择性的阅读这篇博客

类型基础

JavaScript有以下八大类型,除了object类型,其他都为基本类型

  • number
  • string
  • boolean
  • null
  • undefined
  • object
  • symbol
  • bigint

他们的类型都可以直接被typeof识别,特例是

  • typeof null"object"虽然它是null类型的值
  • typeof function(){}"function"虽然它理论上是object类型的

虽然你可能已经为这种特例所不解,但其实这才刚开始,大的还在后面

类型转换

转换为数字

JavaScript内部有一套抽象的数字转换机制叫ToNumber,这套机制在隐式转换或者部分显式转换其他类型值到数字时会被调用。虽然你可能会被恶心到,但我还是要向你介绍这套机制的规则为

  • string若为数字表达式则转换为其对应数字,否则返回NaN
  • undefined转换为NaN
  • null转换为0
  • true转换为数字1
  • false转换为数字0
  • object类型会依次调用toPrimitive()valueOf()toString()来获取值,并利用上面的规则获取其数字值

ToNumber的转换规则会在以下情况下使用,当然这些情况也可以称作转换数字的“技巧”,看你怎么理解它了:

  • Number(value)
  • + value
  • Math.floor(value)
  • value * x,将一个值做乘法运算

没错,Math.floor(true)+ truetrue * 1都等于1,是不是觉得很荒诞?

'5' + 3或者5 + '3'结果都是字符串'53',因为+在有两个操作值,且其中一个为字符串时,会直接做字符串拼接。所以虽然+ '3'结果为数字3,但5 + '3'的结果不是8

parseInt()parseFloat()只接受string类型,所以转换规则与ToNumber转换机制下的string类型情况相似,但是在处理字符时采取从左到右的扫描直到失败为止的方法,所以parseInt("123hello")结果为123

转换为布尔

JavaScript还有一套针对布尔类型的抽象转换机制叫ToBoolean。因为对于前端逻辑编写来讲,判断一个值是否为真实在太重要了,JavaScript里变量像薛定谔的猫一样,处于存在与不存在、真和假的中间态,所以我们JS开发者都有一个奇怪的脑回路,当看到一个字面量值的时候就开始评估它是“真值”(Trusy Value)还是“假值”(Falsy Value)。
可是,与物理学里薛定谔的猫现象相反,JavaScript里对真假值的定义其实很简单,以下的值均为假值

  • undefined
  • null
  • false
  • +0-00nNaN
  • ""

其他均为真值,任何非空字符串、非0数字、对象都是真值。

转换其他类型值为布尔类型的方法:

  • !!value
  • Boolean(value)
  • !,可将值转换为布尔类型,但是真假结果相反

会隐式的将其他类型值转换为布尔的情况:

  • &&
  • ||
  • if (value)
  • while (value)
  • for (...; value; ...),for循环的第二个测试表达式
  • ? :,三元操作符

恭喜你勇士,读到这里就代表马上你就能知道为什么"18" != true了!!!

等价性

我们都知道,JS当中有松散判断的弱等价==,和严格判断的强等价===两种判断等价方式。强等价要求两个操作值必须为同一类型,且值本身也相等,其行为非常容易预测。弱等价在比较值是否相等前会尝试做一些类型转换,尽可能的让可能为不同类型的两个值变得可以判断。
造成文章开头神奇判断结果的原因就在弱等价==时的类型转换策略上,听我将弱等价的转换规则为你娓娓道来

  • 数字与字符串比较,则将字符串转换为数字
  • 布尔值与任何其他值作比较,都先将布尔值转换为数字
  • nullundefined松散比较结果相等
  • 对象与数字或字符串比较,先调用对象的toPrimitive()获取原始类型值后进行比较

所以,"18" == true进行比较时

  • 由于布尔值的比较规则为将布尔值转换为数字,ToNumber(true)结果为数字1,表达式变为"18" == 1
  • 又因为字符串与数字比较时字符串应转换为数字,则ToNumber("18")结果为数字18
  • 最后表达式实际比较18 == 1,结果为假false

所以没错,以下表达式均为真:"1" == true"0" == falsefalse == ""

结语

了解这个例子后你可能会对JavaScript语言行为设计混乱表达不满,但是上述边界条件可以通过引入TypeScript,避免弱等价判断转而使用严格等价,在隐式类型转换之前使用可预测行为的转换方法对值提前进行处理。
如果你无法采用上面列举的解决办法,那我的建议就是多多关注我的博客,如果觉得不错可以推荐给你的朋友或同事,说不定就能在身边慢慢带动大家采用更令人舒心的写法嘞。

ps. 辛苦读者了,为大家的好奇心与耐心致敬。

标签:类型转换,转换,数字,JavaScript,等价,value,类型,true
From: https://www.cnblogs.com/camwang/p/18242665

相关文章

  • 大学生HTML期末大作业——HTML+CSS+JavaScript美食网站(零食)
    HTML+CSS+JS【美食网站】网页设计期末课程大作业web前端开发技术web课程设计网页规划与设计......
  • 大学生HTML期末大作业——HTML+CSS+JavaScript购物商城(华为手机)
    HTML+CSS+JS【购物商城】网页设计期末课程大作业web前端开发技术web课程设计网页规划与设计......
  • C# JavaScriptSerializer序列化时的时间处理详解
    原文链接:https://www.jb51.net/article/122143.htm输出如下图所示: 猜测这里是由于js初始化时间的时候往往是向1970/01/01添加毫秒数,JavaScriptSerializer进行序列化的时候也会格式化为距离1970/01/01到当该时间点GMT+0时间的毫秒数,如果直接反序列化可以看到少了8小时,且......
  • JavaScript中什么是类,如何使用?
    在JavaScript中,类是一种用于创建对象的模板。它定义了对象的属性和方法,并可以通过实例化来创建具体的对象。类提供了一种结构化的方式来组织和管理代码,使得代码更易于理解和维护。下面我将通过三个例子来详细说明JavaScript中类的概念和使用方法。例子1:创建一个表示人的类cl......
  • JavaScript基础语法
    原文链接:https://blog.csdn.net/m0_67683346/article/details/1275910796.2、console.log在控制台打印一个日志(一般是给程序员看的):console.log("helloJavaScript");需要在开发者工具中的控制台查看打印结果:  ★console是JS中的一个“对象”,.表示取对象中的某个属性或......
  • 【JavaScript】内置对象 - 字符串对象 ⑦ ( String 字符串替换 | replace 函数 | repl
    文章目录一、String字符串替换1、replace函数替换字符串2、使用replace函数替换所有匹配字符串3、replaceAll函数替换字符串二、String字符串转数组1、split函数切割字符串2、代码示例-切割字符串String字符串对象参考文档:https://developer.mozilla.......
  • JavaScriptSerializer 类
    原文链接:https://learn.microsoft.com/zh-cn/dotnet/api/system.web.script.serialization.javascriptserializer?view=netframework-4.8.1&redirectedfrom=MSDN命名空间:System.Web.Script.Serialization程序集:System.Web.Extensions.dll 对于.NETFramework4.7.2及更高......
  • JavaScript基础用法(变量定义、输入输出、转义符、注释和编码规范)
    天行健,君子以自强不息;地势坤,君子以厚德载物。每个人都有惰性,但不断学习是好好生活的根本,共勉!文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。文章目录JavaScript基础用法1.变量1.1语法1.2示例代码1.3浏览器效果2.输入和输出2.1输出2.1.1输......
  • 【JavaScript脚本宇宙】万彩世界:探索JavaScript图形与图像库的奇妙之旅
    创意无限:解锁JavaScript图形库的无限可能性前言在Web开发中,图形和图像库扮演着至关重要的角色,为开发人员提供了丰富的工具和资源来创建引人入胜的视觉效果。本文将介绍一系列流行的JavaScript库,涵盖了从2D矢量图形到音乐符号的各种应用领域,帮助您更好地了解和选择适合您项......
  • 【JS封装-兼容IE(较旧版本如IE8及以下)】强化编程实践:精选JavaScript函数封装集锦-添加E
    目录添加Event监听获取非行间样式JSON.parse与JSON.stringifyquerySelector与querySelectorAll的兼容支持跨浏览器的classList操作兼容性处理console.log兼容性处理forEach方法Promise的兼容性处理FetchAPI的兼容性处理添加Event监听IE8及以下版本不支持addEvent......