作者:KAAAsS's blog

来源:https://blog.kaaass.net/archives/929?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io

逛知乎的时候发现@DDDD转了一张图,这张图对js魔法的吐槽可谓非常到位。下面,我们就从这张图出发来详细讲讲js。


数字类型与精度问题

虽然js是弱类型语言,声明变量时也不需要显式指定类型。但是,数据本身依旧还是有类型的,比如数字和字符串就是以不同形式存在的数据。在js中,所有数字的类型都为number。其中,一个特殊的数字就是NaN(Not a number),虽然名字叫“不是数”,但为了计算的一致性(IEEE745亦规定),NaN依旧是数字类型的。任何NaN参与的数字计算的结果都还是NaN。(NaN-NaN!=0)还需要注意的是,js中被0除非但不会报错,而且结果也不是NaN(只有0/0是NaN),而是Infinity(被除数为正)或-Infinity(被除数为负)。

由于将整数和浮点数统一处理,所以js并不存在整数和浮点数的区别——所有数字都以64位有符号浮点数(IEEE745格式)的形式存储。因此,舍入误差是js数字类型的一个大坑。最经典的当然就是0.1+0.2!=0.3了。其实这不是js的锅,大部分编程语言都有这个问题。简单的解释可以查看http://0.30000000000000004.com。很多人对浮点数都有误解,认为0.1是1×10−11×10−1,所以可以正确的表示0.1,然而浮点数并不是这样。在2为基数的情况下,0.1=1/10是一个无限循环小数,所以在运算时会产生舍入误差。想要进一步了解可以查阅有关数值计算的材料。


Max、Min与函数参数

在js中,函数参数也是一种魔法。一般编程语言中,形参具有类似“约束”的作用,即实参的数量要与形参相符(默认值除外)。但是js魔法并不需要形参和实参相匹配,多的实参忽略,少的就是undefined。事实上,js还提供了一种访问参数的方法。在函数体上下文中,js提供了arguments(类似Python的*args)以便参数的访问。考虑到没有卵用的形参,js函数的形参更像是一个别名。

在Python中,函数重载可以通过默认值实现,而在js中,你可以随心所欲的解析arguments,可以说是很硬核了。

回到我们的max和min。EMCAScript v3之后,max和min就支持任意数量参数的调用了。从逻辑上考虑,既然没有传入任何数,那取最大的函数就不能返回一个能大于任何数的数,所以返回-Infinity不无道理。min亦然。

魔法操作符+、-

为了更好的理解接下来的坑,我们有必要先看看+、-两个操作符。这俩操作符神奇就神奇在,他们不仅仅是双目运算符,也同时是单目运算符!对于+,双目运算时其意义是数字加或字符串拼接。这里有个很坑的地方,就是只要参与运算的值不全是数字,那么+就会被视为字符串拼接(String.concat),从而把所有参数转换为字符串并进行拼接。单目运算时,+被视为取正,所有传入的参数都会被转换为数字并取正。(然而取正并没有任何卵用,所以其实就是转为数字)

相比之下-就和蔼了许多,双目是数值减,单目这是取反。

无奈的解释器

下面这个魔法涉及到的东西很多,不过我还是打算把它归类到解释器的范畴,而且这个锅要丢给REPL。{}+[]具歧义,可以被理解为:

  • (作为值理解)对象{}+数组,+为双目

  • (作为代码块理解){}为代码块,+是单目

而这两种理解下的结果也是不同的。而在REPL的上下文下,js解释器采用了第二种理解。而一旦上下文变化,提示解释器这是表达式时,解释器就会采用第一种理解。比如console.log({}+[])的结果就不再是0了。

隐式类型转换

之前在说+、-的时候,我提到了一些隐式的转换,其实这样的转换远不止出现在+、-。比如取反!,就会转成布尔型再取反。所以!+[]就是true,![]是false。考虑到运算优先级,最后得到”truefalse”。

作为一个弱类型语言,js的逻辑是,如果类型不对,那就转过去。

==与===

这是个老生常谈的东西了。这里不多讲,只要知道==可能会隐式转换类型就行。


后记

我写这篇文章的目的并不是解释这张图,因为这张图里的很多知识并不是实际编程所需要的(就像i+++++i,这些是我认为不重要的知识)。我是希望借这张图聊到一些js的语法特性,以加深对js的理解。这两点在我看来有本质的区别。

-END-

 近期热文:

  • Java 11将于本月25日发布,新特性一览

  • 印象笔记终于支持Markdown了 !你还会再用其他笔记吗?

  • 这位闯进程序员界的维密天使,她到底可以编出什么?!

  • 如何从ActiveMQ平滑迁移到Kafka?

  • 系统优化总结—系统层面

  • NIO相关基础篇

  • 以Dubbo为例,聊聊如何为开源项目做贡献

  • 25个面试中最常问的问题和答案

关注我

点击“阅读原文”,看本号其他精彩内容

从一张搞笑图看JavaScript的语法和特性相关推荐

  1. 一张“神图”看懂单机/集群/热备/磁盘阵列(RAID)

    一张"神图"看懂单机/集群/热备/磁盘阵列(RAID) 单机部署(stand-alone):只有一个饮水机提供服务,服务只部署一份 集群部署(cluster):有多个饮水机同时提供 ...

  2. 一张脑图看懂BUI Webapp移动快速开发框架【上】--框架与工具、资源

    前言 之前写过一篇 2018开发最快的Webapp框架--BUI交互框架 ,如果你还没看过,可以简单看一下,主要介绍了BUI的基本功能,有多少控件,以及实现的思路,BUI 1.5版本以后变化很大,统一 ...

  3. bmp180气压传感器工作原理_40张动图看懂各种传感器工作原理

    传感器(英文名称:transducer/sensor)是一种检测装置,能感受到被测量的信息,并能将感受到的信息,按一定规律变换成为电信号或其他所需形式的信息输出,以满足信息的传输.处理.存储.显示.记 ...

  4. 【物理动图】物理老师一针见血:50张动图看懂高中物理

    全世界只有3.14 % 的人关注了 青少年数学之旅 相互作用 作用力与反作用力的特点是什么? 摩擦力的大小跟什么有关系? 图中两个弹簧的弹力大小是否一样?若一样,为什么? 自行车前后轮所受力的方向是什 ...

  5. 一张动图看懂常用的通信协议

    这些显示电子系统中信号波形的动图,有助于帮助我们理解传输的机理. 1 SPI传输 ▲ 图1  SPI 数据传输 ▲ 图1.2  SPI数据传输(2) ▲ 图1.3  SPI时序信号 2 I²C传输 ▲ ...

  6. php搞笑图,这5张只有程序员才能看懂的搞笑图!

    原标题:这5张只有程序员才能看懂的搞笑图! 1.昨天晚上下班回家,一民警迎面巡逻而来. 突然对我大喊:站住! 民警:int类型占几个字节? 我:4个. 民警:你可以走了. 我感到很诧异. 我:为什么问 ...

  7. WebAssembly能不能取代JavaScript?15张卡通图给你答案!

    一切能用JavaScript实现的,终将用JavaScript实现. 一切能编译为WebAssembly的,终将编译为WebAssembly. 前端er们,WebAssembly用上了吗?在浏览器中快 ...

  8. 一篇文章一张思维导图看懂Android学习最佳路线

    一篇文章一张思维导图看懂Android学习最佳路线 先上一张android开发知识点学习路线图思维导图 Android学习路线从4个阶段来对Android的学习过程做一个全面的分析:Android初级 ...

  9. 一张图看懂图像识别算法发展历史

    一张图看懂图像识别算法发展历史

最新文章

  1. python自带的库有哪些_python常用的内置库
  2. 2020 年值得再读一遍的网易云信技术干货 | 上篇
  3. 程序员/设计师能用上的 75 份速查表
  4. python_atp框架
  5. CodeForces - 1312D Count the Arrays(组合数学)
  6. Spring Mvc Url和参数名称忽略大小写
  7. eclipse环境配置、快捷键及基本操作
  8. Spring Reactor教程
  9. 第三十二期:MySQL常见的图形化工具
  10. MATLAB注释快捷键、绘图选项
  11. FORM开发实现动态LOV
  12. [转贴]怎样学好法语?
  13. Stata15 Unicode:一次性转码,解决中文乱码问题
  14. 如何简单地将工资单发给员工?
  15. 保险场景化与场景即保险——新保险
  16. V2X主要用到什么技术?
  17. 女朋友要求道歉100遍:普通人和程序员的做法分别是:
  18. mac m1使用picGo + gitee搭建免费图床
  19. 分库分表基础知识总结
  20. 【ShaderGraph】道路引导,小溪流水等UV动画效果

热门文章

  1. gdb汇编调试c程序
  2. ring0下的 fs:[124]
  3. Linux中的清屏命令
  4. php for循环执行函数,自执行函数用for结束后面不能访问循环变量
  5. java 7 g1_java7中G1垃圾收集器使用和流程总结
  6. NeHe教程Qt实现——lesson13
  7. Linux内核网络(一)——初探内核网络
  8. python下的橡皮线_python线性代数常用操作
  9. intellij_我最喜欢的IntelliJ IDEA功能
  10. isnull pivot server sql_SQLServer行列转换 Pivot UnPivot