博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS笔试题中的类型转换
阅读量:7129 次
发布时间:2019-06-28

本文共 3101 字,大约阅读时间需要 10 分钟。

分享一道笔试题:

let x = {    toString(){        return 20;    },    valueOf(){        return '30';    }}console.log(x == '20');console.log(x == 30);复制代码

答案是false true 为什么?

让我们回到红宝书中,对于相等描述符是这样表述的:

==是相等操作符,如果两个操作数相等,则返回true,而不相等操作符由叹号后更等于号(!=)表示,如果两个操作数不相等,则返回true,这两个操作符都会先将操作数强制转换,再进行比较。 一般遵循下面规则:

  • 如果一个操作数是字符串。另一个操作数是数值,在比较相等性之前先将字符串转换为数值。

  • 如果一个操作数是对象,另外一个不是,则调用对象的valueOf()方法,用得到的基本类型来进行比较。

  • null和undefined是相等的。

  • 要比较相等性之前,不能将null和undefined转换成其他任何值。

  • 如果有一个操作数是NaN,相等操作符返回false,不相等操作符返回true。 回到题目,因为在两次比较中,x是对象另外一个都不是对象,就会调用对象的valueOf方法。所以就会变成

    console.log(x.valueOf() == '20') //console.log(30 == '20')console.log(x.valueOf() == 30) //console.log('30' == 30)复制代码

之后就是字符串与数值比较,字符串先转换为数值,然后判断就可以了。

其实对于这道题,就延伸出了JS中一个令大家都感到头疼的类型转换!! 那我们就来看看吧!

原始值到原始值(数字,字符串,布尔值)的转换

  1. 原始值转化为布尔值,所有的假值("undefined","null",0,-0,NaN,"")都会被转化false,其他都会被转化为true.

  2. 原始值转换为字符串相当于加""

  3. 原始值转化为数字,布尔转文字:true --> 1,false --> 0 字符串转数字,只有字符串中都是以数字表示的,就可以直接转换为字符串,如果两个数字间有空格的话,那么转换结果就是NaN.

    +"123"  //123 +"1 3" // NaN复制代码

对象到原始值的转换

  1. 对象转换为布尔值都是true
  2. 对象到字符串
  • 如果对象有toString()方法,就调用toString()方法,如果这个方法返回原始值,就将这个对象转化为字符串。
  • 如果对象没有toString()方法或者该方法返回的不是原始值,那么就会调用该对象的valueOf()方法,如果存在就调用这个方法,如果返回值是字符串就转换为字符串。
  1. 否则就报错。

+运算符如何进行类型转换。

  1. 如果作为一元运算符就是转化为数字,常常用来将字符串转化为数字。

    +“2” //2复制代码
  2. 如果作为二元运算符就有两种转换方式

  • 两边如果其中一边有字符串,就会将另外一边转化为字符串进行拼接。
  • 如果两边没有字符串,两边都会转化数字相加,对象也会根据前面的的方法转化为原始值数字。
  • 如果其中的一个操作数是对象,则将对象转换为原始值,日期对象会通过toString(),其他对象会通过valueOf()方法进行转换,但是大多数对象都是不具备可用的valueOf()方法,所以还是会通过toString()方法执行转换。(也就是先用valueOf再用toString方法)

让我们来看看一道经典题目吧!

(! + [] + [] + ![]).length复制代码

运算顺序应该是这样的:

  1. 首先,![]会转换为"false", +[]会转换为0,此时式子变成

    !0 + [] + false复制代码
  2. !0 转换为 true,此时式子变成 true + [] + false

  3. 第三步中间的 []会转为空字符串,在+ 运算符如何进行类型转化第二条的第三点,对象会被转化为原始值,就是空字符,所以经过第三步之后就会变成

    "true" + false复制代码
  4. "truefalse"复制代码
  5. "truefalse".length = 9复制代码

可能你看到这里就有点疑问,为什么![]是false?

逻辑非运算符

简单的来说,就是首先把数据转化为布尔值,然后取反,结果为true或false。 根据规则: 原始值转化为布尔值,所有的假值("undefined","null",0,-0,NaN,"")都会被转化false,其他都会被转化为true. 所以![] = !true = false

toString和valueOf方法

上面不止一次的提到了toString和valueOf方法,那这到底是怎么计算的?

  • toString用来返回对象的字符串表示

    var obj = {};  console.log(obj.toString());//[object Object]  var arr2 = [];  console.log(arr2.toString());//""空字符串  var date = new Date();  console.log(date.toString());//Sun Feb 28 2016 13:40:36 GMT+0800 (中国标准时间)复制代码
  • valueOf方法返回对象的原始值,可能是字符串、数值或bool值等,看具体的对象。

    var obj = {    name: "obj"  };  console.log(obj.valueOf());//Object {name: "obj"}  var arr1 = [1];  console.log(arr1.valueOf());//[1]  var date = new Date();  console.log(date.valueOf());//1456638436303复制代码

    如代码所示,三个不同的对象实例调用valueOf返回不同的数据

总结一波

  1. undefined == null,结果是true。且它俩与所有其他值比较的结果都是false。

  2. String == Boolean,需要两个操作数同时转为Number。

  3. String/Boolean == Number,需要String/Boolean转为Number。

  4. Object == Primitive,需要Object转为Primitive(具体通过valueOf和toString方法)。

写在最后

//大坑    console.log ( [] == 0 );//true    console.log ( ! [] == 0 );//true    //神坑    console.log ( [] == ! [] );//true    console.log ( [] == [] );//false    //史诗级坑    console.log({} == !{});//false    console.log({} == {});//false复制代码

好好思考一下上面的坑吧!

参考资料:

https://segmentfault.com/a/1190000008432611 https://mp.weixin.qq.com/s/wd8JLGtnsoQYfm3K7KXO0g

转载于:https://juejin.im/post/5c850c4d6fb9a049ab0e6faa

你可能感兴趣的文章
安卓的开端的相关配置
查看>>
1108. Finding Average (20)
查看>>
Ubuntu下XTerm乱码问题的解决及XTerm的简单配置
查看>>
HDU 1215
查看>>
大神是怎样炼成的 ---谈如何做一个优秀的程序员!
查看>>
js数组去除重复数据
查看>>
一个骚气的前端JS代码生成网站
查看>>
在springmvc中使用requestContextListener获取全部的request对象
查看>>
Jenkins_KillProcess
查看>>
MySQL 获得当前日期时间 函数
查看>>
《Nginx:取代Apache的高性能Web服务器》学习笔记(一)
查看>>
创建数组的方法
查看>>
layui的几个简单使用(简单弹窗,加载效果,移除加载效果)
查看>>
【linux操作命令】mysql
查看>>
postgresql支持sys_guid()
查看>>
cede词根
查看>>
怎么删除有外键约束的MySQL表中的数据
查看>>
Spring AOP的切入点表达式
查看>>
libevent
查看>>
python编程中的if __name__ == 'main' 的作用和原理
查看>>