原始值转原始值
转字符串
String(undefined); // -> 'undefined'
String(null); // -> 'null'
String(3); // -> '3'
String(true); // -> 'true'
String(false); // -> 'false'
转数字
Number()
方法转换数字时,如果出现非数字的字符时会直接返回NaN(null 、布尔值除外),且可以识别浮点数。parseInt()
方法,首先是可以将数字或者字符串转换成为一个整数数字,如果字符串的第一个字符不能被转换为数字,直接返回NaN;字符串中出现不能转为数字的字符,该方法会进行截取操作。方法还有第二个参数(可选),表示要解析数字的基数,介于2~36之间。(该篇主要讨论数据类型的转换,所以在此不做过多介绍。)
Number(undefined); // -> NaN
Number(null); // -> 0
Number('3'); // -> 3
Number('.3'); // -> 0.3
Number('1 3'); // -> NaN
Number('3a'); // -> NaN
Number('a3'); // -> NaN
Number(true); // -> 1
Number(false); // -> 0
Number(''); // -> 0
parseInt(undefined); // -> NaN
parseInt(null); // -> NaN
parseInt('3'); // -> 3
parseInt('.3'); // -> NaN
parseInt('0.3'); // -> 0
parseInt('3 1'); // -> 3
parseInt('3a'); // -> 3
parseInt('a3'); // -> NaN
parseInt(true); // -> NaN
parseInt(false); // -> NaN
转布尔值
这里就涉及到一个虚值(falsey)的概念
虚值:undefined、null、0、false、NaN、’’。(注意''
和' '
可不一样,空格属于一个字符)
只要是虚值转换布尔值都为false,反之都为true。
Boolean(' '); // -> true
Boolean(''); // -> false
Boolean(undefined); // -> false
Boolean(null); // -> false
Boolean(0); // -> false
Boolean(false); // -> false
Boolean(NaN); // -> false
引用类性值转原始值
引用类性值转数字
- 首先通过
valueOf()
方法,看其返回值是否是原始值。 - 如果为原始值,直接通过
Number()
方法转换为数字。 - 如果是非原始值,则调用其对应类型的
toString()
方法(基于原型链查找)。 - 如果返回的值是原始值,直接通过
Number()
方法转换为数字。 如果通过重写
toString()
更改了返回值,返回的是一个对象的话,直接报错。注意:
valueOf()
方法,如果没有被我们重写的话,默认返回的就是自身。Number({});
// {}.valueOf() -> {} -> {}.toStirng() -> '[object Object]'
// -> Number('[object Object]') -> NaN
Number([]);
// [].valueOf() -> [] -> [].toStirng() -> '' -> Number('') -> 0
Number(function () {});
// (function () {}).valueOf() -> (function () {}).toString() -> 'function () {}' -> Number('function () {}') -> NaN
引用类性值转字符串
先通过
toString()
方法, 看其返回值是否是原始值。- 如果是原始值,调用其包装类所对应的
toString()
方法。 - 如果是重写的
toString()
返回的是引用类型值,则调用valueOf()
方法。 - 如果返回原始值,调用其包装类所对应的
toString()
方法。 - 如果还是引用类型值,直接报错。 ```javascript // 这种两种转换方式是等效的 String([]) === ‘’ + [];
String(undefined); // -> ‘undefined’ String(null); // -> ‘null’
var obj = { toString () { return []; }, valueOf () { return {}; } } String(obj); // 报错 Uncaught TypeError: Cannot convert object to primitive value at String
var obj1 = { toString () { return []; }, valueOf () { return 3; } } String(obj1); // -> ‘3’
var obj2 = { toString () { return true; }, valueOf () { return 3; } } String(obj2); // -> ‘true’
<a name="wrpUg"></a>
## 双等隐式转换规则
引用类型值和原始类型值进行比较时,都通过`Number()`方法转为数字后进行比较。<br />两个引用类性值比较时,会根据指针(栈内存中的引用地址)进行对比。<br />特例:<br />`undefined == null // -> true`,undefined 和 null 除了彼此相等和自己相等之外,与其他任何类型的值都不相等。<br />`NaN == NaN // -> false`,NaN 与任何值都不相等包含自己本身。
```javascript
undefined == null // -> true
NaN == NaN // -> false
// question
console.log([] == ![]);
console.log({} == !{});
/**
* "!" 逻辑运算符 优先级 17
* !expr 若 expr 可转换为 true, 则返回 false;否则, 返回 true
* "==" 比较运算符 优先级 11
* 相等比较操作符会为两个不同类型的操作数转换类型
*/
/**
* [] == ![]
* 先运算 ![] []不是一个虚值, 转布尔值就为true, !true -> false;
* [] == false
* [] -> [].valueOf() -> [] -> [].toString() -> '' -> Number('') -> 0
* false -> Number(false) -> 0
* 0 == 0 -> true
*/
/**
* {} == !{}
* 先运算 !{} {}不是一个虚值, 转布尔值就为true, !true -> false;
* {} == false
* {} -> {}.valueOf() -> {} -> {}.toString() -> '[object Object]' -> Number('[object Object]') -> NaN
* false -> Number(false) -> 0
* 0 == NaN -> false
*/