javascript类型转换

从原理上讲一下 javascript 的隐式类型转换,10分钟学会类型判断原理。

内置七种基本类型

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

typeof返回的是类型的字符串值,但是null是例外,typeof null === 'object',这是个bug

typeof function的返回值也不是基本类型的字符串值,是因为functionobject的一个子类型

typeof function a(){} === 'function';   //true

详情见typeof 规范

typeof.png

位运算符

位运算符要求的是32位整数,小数位和超过32位的整数位忽略

  • |按位或运算符可以将小数转换成整数a | 0,不过要注意整数不能超过32位

  • ~按位非运算符将操作数所有位取反,在javascript中相当于-(x+1)

//5 二进制 101,补满 32位
00000000000000000000000000000101
//按位取反
11111111111111111111111111111010
//由于32位开头第一个是1,所以这是一个负数,将二进制转换成负数,需要先反码
00000000000000000000000000000101
//之后,再+1
00000000000000000000000000000110
//转换成十进制为6,加上符号变成负数 -6

一个应用是~-1 == 0可以替换

if(arr.indexOf('a') > -1) {}

if(~arr.indexOf('a')) {
    //有值
}

~~a也可以将a取整

一元运算符

  • +运算符把操作数转换成数字
  • -运算符把操作数转换成数字再改变结果的符号
//涉及到类型转换,下面讲
+[]; //0
+'42'; //42
//++ --会被识别为运算符,所以使用时要加空格
5 + +'3'; //8

类型转换

基础概念就不写了,直接来容易迷糊的and原理,抛几个问题

[] == ![]; //true
"0" == ""; //false
"" == 0; //true
"foo"  == ["foo"]; //true

ToPrimitive

首先介绍一下es内部抽象操作ToPrimitive,它的作用是将输入转换成非对象类型数据,最后的返回值是基本类型值,或者抛错

The abstract operation ToPrimitive takes an input argument and an optional argument PreferredType. The abstract operation ToPrimitive converts its input argument to a non-Object type.

Paste_Image.png

ToPrimitive转换对象的时候调用[[DefaultValue]]内部方法,可带一个参数hint,代表如果这个对象可以转成多种基本类型值,我们把它转成哪种,默认是Number

[[DefaultValue]]的转换办法是

  • hintString的话先看有没有toString方法,有调用toString,如果是基本类型值则返回,否则看有没有valueOf方法,有调用valueOf,是基本类型值返回,不是的话抛TypeError错误
  • hintNumber的话则是先看valueOf方法,后看toString方法
  • 没有hint参数则按Number的规则转,Date对象例外,用String

字符串和数字之间的隐式强制类型转换

var a = [1,2];
var b = [3,4];

a + b; //'1,23,4'

+ 加号转换原则简单说就是某个操作数是字符串,或者可以通过ToPrimitive转成字符串,那就执行字符串拼接操作,否则进行数字加法。

[1,2]是个对象,调用内部的[[DefaultValue]]方法,valueOf方法得到的是[1,2]不是基本类型值,调用toString得到字符串'1,2'[3,4]同理,最后执行字符串拼接得到'1,23,4'

疑惑

[] + {}; //"[object Object]"
{} + []; //0

这里先说一下后者,因为{}在javascript里被识别为代码块,自己就执行了,所以{} + []被解析成+ [],这里的+是一元运算符,将[]转换成数字,也就是通过ToPrimitive得到字符串"",转成数字为0
前者被解析成了字符串拼接,""+[object Object]

宽松相等和严格相等

“ ==允许在相等比较中进行强制类型转换,而 === 不允许”

规范里算法很多,挑几个代表性的

一、Number Compare String
Paste_Image.png
二、Boolean Compare with other
Paste_Image.png
三、Object Compare with String or Number
Paste_Image.png
四、null == undefined

现在来看一下之前提出的几个问题

//![]转换成boolean值为0,[] == 0,[]根据规则进行ToPrimitive([]),得到"" == 0,再转成 ToNumber("") == 0
[] == ![]; //true

//字符串比较
"0" == ""; //false

//ToNumber("") == 0
"" == 0; //true

//ToPrimitive(["foo"]) == "foo"
"foo" == ["foo"]; //true

收获

明白了隐式类型转换规则,平时写代码的时候也要注意,不要写容易让别人困惑的代码;
最大的收获是查官方规范,看别人的博客太麻烦了,这里讲的不清楚,那里讲的模模糊糊,直接看规范,一看就懂了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Javascript 中有6种基本类型(包括 symbol),以及对象类型,他们在不同的运算中会被系统转化为不同是...
    faremax阅读 844评论 0 3
  • 原始值转换: 对象转换为原始值 对象都会从Object继承valueOf 和toString 方法。默认的valu...
    softbone阅读 140评论 0 0
  • 1.deputy n. 代理人,代表 adj. 副的;代理的 仿 He delegated his respons...
    倦鸟归矣阅读 119评论 0 0
  • 我是日记星球164号宝宝,我承诺每天如实如是的发表一篇日记,记录每天的生命历程。感恩所有同学家人的支持与鼓励!我相...
    韦炜阅读 160评论 0 2
  • 这几天被刘洲成家暴的新闻刷屏了。至上励合的成员之一,在唱歌方面没红,却因家暴红了。 刘洲成的老婆林苗在公开的家书中...
    谜秋阅读 487评论 0 0