资讯专栏INFORMATION COLUMN

js的类型转化三两事儿

vpants / 1801人阅读

摘要:即在这个隐式强制类型转换中,即不会等于也不会等于。按照正常人类的脑回路,应该是将先转换为布尔值,然后再将两个布尔值对比。为什么和就可以避开操作符的坑呢它们进行强制类型转换时的转换规则又是怎样的。

在js中,类型转换是一个被非常多人诟病的地方。新手看了会发矇,老手看了会头疼。

类型转换,又成为强制类型转换,主要区分为显式强制类型转换隐式强制类型转换

按我理解,类型转换的意思就很明显,就是当程序运行时需要此刻的变量的类型与变量的实际类型不符时,就会进行强制转换,在一些静态语言中,这个过程发生在编译阶段,或者干脆就抛出错误。而在js中,这个转换过程发生在运行时,所以你写代码的时候并不会意识到自己已经掉进坑里了。

显式强制类型转换,简单的说,就是你觉得你可以明面上一眼看出来的,比如‘’ + number,+string,Boolean(value); 而隐式强制类型转换就是反过来的意思。

举个栗子:

var a = "value";
if (a == true) {
  console.log("a is true");
} else if (a == false) {
  console.log("a is false");
}

按照正常的脑回路,一般人不会这么写。但是确实是有人会写if (a == true) {...}这种语句,当然,后面的else if (a == false)是为了节目效果加的。即便是这样,a == true这种写法也是不可取的。

最后的输出是,两个都不输出。即在这个隐式强制类型转换中,a即不会等于true, 也不会等于false。

首先解释一下为什么a既不等于true, 也不等于false。按照正常人类的脑回路,应该是将a先转换为布尔值,然后再将两个布尔值对比。这种情况下,a转成布尔值只能转换成true或者false。要是这么想,那你就是too young, too simple了

当使用相等操作符==进行判断时,将遵循以下规则(来自红宝书):

· 如果又一个操作数是布尔值,则在比较相等性之前先将其转换为数值(false转换为0,而true转换为1
· 如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值
· 如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照之前的规则进行比较
· null和undefined是相等的
· 要比较相等性之前,不能将null和undefined转换成其他任何值
· 如果一个操作数是NaN,则相等操作符返回false。
· 如果两个操作数都是对象,则比较它们是不是同一个对象,是则返回true,否则返回false

所以就可以知道上例中,转换是如何进行的。首先两个相等操作的操作数中都包含布尔值,先将布尔值转换为数值所以这里true转换为1,false转换为0。接下来再次进行比较,此时两对操作数中都包含一个字符串操作数,则将字符串转换为数值, a转换为数值是NaN,此时再次进行比较,由于有一个操作数是NaN,按照规则,返回false。所以a既不等于true也不等于false。

由上可以看出,使用==进行条件判断的时候是非常具有危险性的,尤其是当其中一个操作数为true的时候,如果另一个操作数不为布尔值,则很有可能就掉进坑里了。

那么一般在判断的时候怎么去进行判断比较好呢。我认为尽量不使用==操作符。使用===进行全等判断,或者直接将你需要判断的值丢进if判断里,比如if (a == true)可以改成if (a)或者if (!!a)这样就能避开==操作符的坑了。如果一定要使用==进行比较,不用不舒服,则最好先将操作数进行显式类型转换为同一类型的数据,再进行比较,

知其然就要知其所以然。
为什么if (a)if (!!a)就可以避开==操作符的坑呢?它们进行强制类型转换时的转换规则又是怎样的。

其实在if的判断语句块内,如果判断值不是布尔值的话,会自动调用Boolean()函数进行布尔值的转换。而!!则相当于一次Boolean()的值类型转换了。所以在if的判断语句里直接放入判断条件和显式的将判断条件进行转换,其作用是一样的。区别也只是在于是否对后续看代码的人友好了,如果后面代码维护可能是接触代码不深的新手,则建议进行显式的转换。

由上面的解释可以知道if (a)if (!!a)if (Boolean(a))的作用是一样的,所以这里只要了解一下Boolean()函数的转换规则就可以了:

任何非空字符串为true,空字符串("")为false
任何非零数字值(包括无穷大)为true,0和NaN为false
任何对象为true,null为false
undefined为false

以上规则来自红宝书,部分内容省略

看以上的Boolean()函数的转换规则,与我们日常工作中所需要的类型转换是非常契合的。
比如我们普遍会认为并要求if可以拦截空字符串,false,null,undefined,0与NaN

需要注意的是,虽然红宝书上并没明确指出,但三元运算符( ? : )使用的转换规则也是Boolean()函数的转换规则.

而除了条件判断,在其他一些操作里也会出现类型转换,比如关系操作符(<, >, <=, >=):

var a = "23";
var b = "3";
console.log(a < b); // true

上面这个转换可能很多的前端开发工程师都掉进过坑里并摸不着头脑。
可能你也看出来了出现‘23’小于‘3’的原因或许是在于它们都是字符串。如果关系操作符(<,>,<=,>=)两边都是字符串,则比较两个字符串对应的字符编码。"2"的字符编码是50,而3的字符编码是51,所以这里出现了‘23’小于‘3’的情况。

到这里很多人都会惊叹一声,并表示记住了此知识点。但是这样往往是不够的,你需要深挖下去,需要确切的了解关系操作符的转换规则,才能确保不会再次掉进它的坑里。

如果两个操作数都是数值,则执行数值比较 如果两个操作数都是字符串,则比较两个字符串对应的字符编码值
如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较
如果一个操作数是对象,则调用这个对象的valueOf()方法,并用得到的结果根据前面的规则进行比较
如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较
如果一个操作数是NaN,undefined,则返回false
如果操作数为null, "", 则转换为0进行比较

多看看红宝书就会发现js中的类型转换其实坑还是很多的,还有一些加减乘除的操作符本身也会产生类型转换的问题。但是基本问题不是太大,所以就不多带带拎出来了。

最后,一道思考题:

// do something ...
console.log(typeof a); // "object"
console.log(a == false); // true

上面的对象为什么会等于false,这个题是之前刷到的一道面试题,可不是我瞎编的。。

最后,欢迎斧正,没有仔细的准备,所以写的少且杂,也是作为自己的一个总结回顾吧。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105183.html

相关文章

  • 推荐三两款前端动画库,anitmate.css, velocity-animate, anime,

    摘要:所以就说说吧优点可自定义动画效果,支持队列动效支持回调函数支持动画的,等等功能缺点缺少自定义特效文档比较少使用遇到的小问题默认不是匀速的,需要设置详细整理待续 在最近一段时间的工作里,常常用到动画,我主要接触了三个 animate.cssanimevelocity 下面分析一下他们的优缺点 animate.css 优点:animate.css主要是使用css实现动画效果,目前已经有几十...

    xzavier 评论0 收藏0
  • Vue父子组件通信三两事(prop、emit)

    摘要:的单向数据传递直接作为一个本地变量下面是我的子组件这是父组件给我传的数据运行结果如下图子组件向父组件传递数据基本使用子组件向父组件传递数据,不能像上面一样实时的传递数据,必须通过事件触发。 组件是Vue核心功能之一,合理的组件化,可以减少我们代码的冗余,提高项目的可维护性。下面,我将由浅入深的讲Vue的组件在讲之前,首先我们先了解一下组件的命名。 HTML是对特征名不敏感的语言,他...

    darcrand 评论0 收藏0
  • JS 中 Array.sort 那些事儿

    摘要:然而有时候的结果和预期结果还是有些差异的。中文的可以通过来获取。啊次比例中毓比侊啊比侊比例次毓中当然和允许传入参数指定,有兴趣的可以去上看看用法。对于中文或者需要本地化比较的场景下,可以使用或者来进行比较。 大家都知道 js 自带了一个排序方法 sort,很多时候需要排序的时候也都直接使用了 sort 方法来排序。然而有时候 sort 的结果和预期结果还是有些差异的。 看下面的代码 [...

    Sike 评论0 收藏0
  • JavaScript核心概念(1):类型转换

    摘要:核心内置类,会尝试先于可以理解为对象优先转换成数字例外的是,利用的是转换。非核心的对象,通过自己的实现中定义的方法转换成原始值。 本文首发于个人博客 showImg(https://segmentfault.com/img/remote/1460000015954811?w=639&h=724); 看到这个是不是有一种想打人的感觉,垃圾 JavaScript,这特么都什么鬼,相信很多...

    tracymac7 评论0 收藏0
  • WebAssembly 那些事儿

    摘要:的目标是对高级程序中间表示的适当低级抽象,即代码旨在由编译器生成而不是由人来写。表示把源代码变成解释器可以运行的代码所花的时间表示基线编译器和优化编 WebAssembly 那些事儿 什么是 WebAssembly? WebAssembly 是除 JavaScript 以外,另一种可以在网页中运行的编程语言,并且相比之下在某些功能和性能问题上更具优势,过去我们想在浏览器中运行代码来对网...

    邱勇 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<