JavaScript数据类型转换
在知乎上刷面试题看到有关JavaScript的数据类型的题目,对这个方面的知识再次回顾。写这篇博客源于一道十分简单的面试题:
1 | function greet(person) { |
但还是插一句:原因是当两个操作数均为对象时,对象是引用类型,它们作为对象进行比较,仅当它们引用相同对象时返回true。
数据类型的定义
数据类型的分类:
基本数据类型: string,boolean,number,symbol(es6新增),undefined,null
内置函数(内置对象): String,Number,Boolean,Function,Symbol,Array,Date,RegExp…..
引用数据类型: Object
数据类型的转换:
隐式转换:
隐式转换在ECMAScript中有所规范:
对象(包括数组) 会首先被转换为相应的基本类型值, 如果返回的是非数字的基本类型值, 则再遵循以上规则将其强制转换为数字。
为了将值转换为相应的基本类型值, 抽象操作 ToPrimitive 会首先(通过内部操作DefaultValue ) 检查该值是否有 valueOf() 方法。 如果有并且返回基本类型值, 就使用该值进行强制类型转换。 如果没有就使用 toString() 的返回值(如果存在) 来进行强制类型转换。
1 | //输出?请解析原理 |
原理:当a+b运算操作时,由于a和b是用“+”连接,导致a和b都要先进行隐式强制类型转换,再做“+”运算。但是由于a和b是数组类型,需要进行取原始值操作,解析器会先对数组先调用valueOf函数,如果有该方法并且返回值是原始类型的话就是这个返回值;否则继续调用toString()方法,如果返回的是原始值,则利用这个返回值进行“加”运算;否则会抛出异常。最后数组a和b最终调用toString()函数输出“1,2”和“3,4”,再通过“+”运算得到结果.
1 | undefined == null; // true |
1.undefined与null相等,但不恒等(===)
2.一个是number一个是string时,会尝试将string转换为number
3.隐式转换将boolean转换为number,0或1
4.对于0、空字符串的判断,建议使用 “===” 。
5.“==”会对不同类型值进行类型转换再判断,“===”则不会。它会先判断两边的值类型,类型不匹配时直接为false。
宽松相等和严格相等 :
宽松相等规范: 比较x==y时,且x和y都有值,会产生true和false的情况,以下比较的情况有
- 如果x和y的数据类型相同时,就相当于x===y
- 当x是null和y是undefined,返回true
- 如果x的数据类型是Number和y的数据类型是String,返回的比较是x==ToNumber(y)
- 如果x的数据类型是Boolean,那么的比较是ToNumber(x)==y
- 如果x的数据类型是String, Number, or Symbol 和y的数据类型是Object 那么返回的是 x == ToPrimitive(y).
严格相等规范: 比较x===y时,且x和y都有值,会产生true和false的情况,以下比较的情况有
- 如果x和y的类型不同,返回false
- 如果x的数据类型是Number:
2.1 如果x是NaN,返回false
2.2 如果y是NaN,返回false
2.3 如果x是-0和y是+0,返回true
2.4 如果x是+0和y是-0,返回true
2.5 如果x和y都是Number且值相等,返回true
显式转换:
一般来说,显式转换是指Number,String,Boolean构造函数,手动将各种类型的值,转换成数字、字符串或者布尔值。
1 | Boolean( "0" ); // true |
对象通过toString或valueOf方法转换为原始值,JS语言核心的内置类首先尝试使用valueOf(),再尝试使用toString()。
对象类型的转换稍微复杂些,对象参与基本类型数据运算时,首先是要将对象转换为基本类型。转换方法如下:
- 调用toString()方法,如果返回基本类型的值,则用String()构造方法转换该值。
- 如果toString()方法返回的不是基本类型,则再调用valueOf()方法,如果返回基本类型的值,则用String()构造方法转换该值。
- 如果valueOf()方法返回的也不是基本类型,就抛出错误,如谷歌抛出:Uncaught TypeError: Cannot convert object to primitive value
String转换对象
- 先调用toString()方法去获得原始类型的值,返回的是原始类型的值,那么调用String()构造函数去返回值
- 如果toString()返回的是对象,那么就要继续调用valueOf()去获得原始类型的值,返回的是原始类型的值,那么调用String()构造函数去返回值
- 倘若valueOf()返回的也不是基本类型,那么抛出错误异常
1 | var a = { |
Number转换对象
- 先调用valueOf()方法去获得原始类型的值,返回的是原始类型的值,那么调用Number()构造函数去返回值
- 如果valueOf()返回的是对象,那么就要继续调用toString()去获得原始类型的值,返回的是原始类型的值,那么调用Number()构造函数去返回值
- 倘若toString()返回的也不是基本类型,那么抛出错误异常
1 | var a = { |
Boolean转换对象
Boolean对象有六个值转换十分特殊,其他的转换为true
1 | undefined null false 0(包括+0和-0) NaN 空字符串('') |
参考链接
- [温故js][https://segmentfault.com/a/1190000005863067#articleHeader9]
- [ECMAScript规范][https://tc39.github.io/ecma262/#sec-abstract-equality-comparison]
- [MDN比较操作符][https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Comparison_Operators]
本文由 Abert 创作,采用 知识共享署名 4.0 国际许可协议。
本站文章除注明转载/出处外,均为本站原创或翻译,转载请务必署名。