类型转换
1、显示类型转换
显示类型转换顾名思义就是用特有的方法对类型进行转换
显示类型转换的方式只有三种:
1、Number()
原始类型转换
- 数值:转换后还是数值
- 字符串:如果可以被解析为数值,则转化为相应的数值会忽略所有前导的 0,否则得到 NaN,空字符串为 0
1
Number("000001"); //1
- 布尔值:true 转成 1,false 转成 0
- undefined:转成 NaN
- null:转成 0
对象类型转换
- 先调用对象自身的 valueOf 方法,如果该方法返回原始类型的值(数值、字符串和布尔值),则直接对该值使用 Number 方法,不再进行后续步骤
- 如果 valueOf 方法返回复合类型的值,再调用对象自身的 toString 方法,如果 toString 方法返回原始类型的值,则对该值使用 Number 方法,不再进行后续步骤
- 如果 toString 方法返回的是复合类型的值,则报错
parseInt 和 parseFloat
- parseInt:只解析整数,当传入的值以‘0x’或‘0X’开头时,会解析成十六进制数
- parseFloat:既可以解析整数又可以解析浮点数
- 共同点:都会跳过任意数量的前导空格,尽可能解析更多数值字符,并忽略后面的内容。如果第一个非空格字符是非法的数字直接量,将最终返回 NaN
2、String()
原始类型转换
- 数值:转为相应的字符串
- 字符串:转换后还是原来的值
- 布尔值:true 转为‘true’,false 转为‘false’
- undefined:转为‘undefined
- null:转为‘null’
对象类型转换
- 先调用 toString 方法,如果 toString 方法返回的是原始类型的值,则对该值使用 String 方法,不再进行以下步骤
- 如果 toString 方法返回的是复合类型的值,再调用 valueOf 方法,如果 valueOf 方法返回的是原始类型的值,则对该值使用 String 方法,不再进行以下步骤
- 如果 valueOf 方法返回的是复合类型的值,则报错
JSON.stringify()
JSON.stringify 底层也是调用了 toString 方法
3、Boolean()
undefined、null、-0、+0、NaN、’’(空字符串)返回的都是 false,除了上述的都是返回 true,包括对象类型
2、隐式类型转换
隐式类型转换同样有三种:
1、+(加号)
1.1 一元+(加号)运算符
查看ES5 规范 11.4.6可以看到,当+(加号)作为一元运算符时,底层会调用 ToNumber 方法去处理,相当于 Number(),当+(加号)后是普通数值时,返回的就是 Number(数值)
1 | +"1"; //1 |
当+(加号)后是对象类型时,对象类型就会像显示类型中所讲:
- 先调用对象自身的 valueOf 方法,如果该方法返回原始类型的值(数值、字符串和布尔值),则直接对该值使用 Number 方法,不再进行后续步骤
- 如果 valueOf 方法返回复合类型的值,再调用对象自身的 toString 方法,如果 toString 方法返回原始类型的值,则对该值使用 Number 方法,不再进行后续步骤
- 如果 toString 方法返回的是复合类型的值,则报错
1 | +[]; //0 []先调用valueof方法返回[],再调用toString方法返回"" |
1.2 二元+(加号)运算符
查看ES5 规范 11.6.1可以看到当 value1+value2 时:
1. lprim = ToPrimitive(value1)
2. rprim = ToPrimitive(value2)
3. 如果 lprim 和 rprim 都是 String 类型时,则直接返回 ToString(lprim)和 ToString(rprim)拼接结果
4. 返回 ToNumber(lprim) 和 ToNumber(rprim)的运算结果
ToPrimitive、ToString、ToNumber 三者皆为内部函数:
ToPrimitive 执行的步骤:
- 如果 obj 为基本类型,直接返回
- 否则,调用 valueOf 方法,如果返回一个原始值,则 JavaScript 将其返回。
- 否则,调用 toString 方法,如果返回一个原始值,则 JavaScript 将其返回。
- 否则,JavaScript 抛出一个类型错误异常。
ToString 相当于 String()
ToNumber 相当于 Number()
按上述规范,对下列几个例子进行讲解:
1 | null + 1; //1 |
1 | undefined + 1; //NaNnull |
1 | [] + []; //'' |
1 | [] + {}; //'[object Object]' |
1 | {} + []; //0 |
1 | {} + {}; //谷歌返回'[object Object][object Object]' 火狐返回NaN |
2、比较运算
2.1 ==相等
同样我们查看ES5 规范 11.9.3中所讲:
比较 x == y,其中 x 和 y 是值,产生 true 或 false。这样的比较执行如下:
1. 如果 x,y 类型相同,则
a. 如果 x 是 Undefined,则返回 true。
b. 如果 x 为 Null,则返回 true。
c. 如果 x 是数字,则
i. 如果 x 为 NaN,则返回 false。
ii. 如果 y 为 NaN,则返回 false。
iii. 如果 x 与 y 相同,则返回 true。
iv. 如果 x 为+0 且 y 为 − 0,则返回 true。
v. 如果 x 为 − 0 且 y 为+0,则返回 true。
vi.返回 false。
d. 如果 x 类型为 String,则如果 x 和 y 是完全相同的字符序列(相同的长度和相同位置的相同字符),则返回 true。否则,返回 false。
e. 如果 x 类型为布尔值,则如果 x 和 y 均为 true 或均为 false,则返回 true。否则,返回 false。
f. 如果 x 和 y 指向同一对象,则 返回 true。否则,返回 false。
2. 如果 x 是 Null 和 y 是 Undefined 的,返回 true。
3. 如果 X 是 Undefined 和 y 为 Null,返回 true。
4. 如果 x 类型是 Number 且 y 类型是 String,则返回比较结果 x == ToNumber(y)。
5. 如果 x 类型为 String 且 y 类型为 Number,则返回比较结果 ToNumber(x)== y。
6. 如果 x 类型为布尔值,则返回比较结果 ToNumber(x)== y。
7. 如果 y 类型为布尔型,则返回比较结果 x == ToNumber(y)。
8. 如果 x 类型是 String 或 Number 且 y 类型是 Object,则返回比较结果 x == ToPrimitive(y)。
9. 如果 x 类型是 Object 并且 y 类型是 String 或 Number,则返回比较结果 ToPrimitive(x)== y。
10. 返回 false。
按上述规范,对下列几个例子进行讲解:
1 | undefined == undefined; //true |
1 | NaN == NaN; //false |
1 | undefined == null; //true |
1 | 1 == "1"; //true |
1 | false == 0; //true |
1 | [] == 0; //true |
2.2 <判断
同样我们查看ES5 规范 11.8.5中所讲:
比较 x < y(其中 x 和 y 是值)会产生 true,false 或 undefined(这表明至少一个操作数是 NaN)。除 x 和 y 外,该算法还使用名为 LeftFirst 的布尔标志 作为参数。该标志用于控制对 x 和 y 进行具有潜在可见副作用的操作的顺序 。这是必需的,因为 ECMAScript 指定了从左到右的表达式求值。LeftFirst 的默认值 为 true,表示 x 参数对应于 y 参数对应表达式左侧出现的表达式。如果 LeftFirst 为假,则相反,操作必须在 x 之前对 y 执行。这样的比较执行如下:
1. 如果LeftFirst标志为true,则
a. 设 px为调用ToPrimitive的结果(x,Number)。
b. 令 py为调用ToPrimitive的结果(y,Number)。
2. 否则需要颠倒评估顺序以保留从左到右的评估
a. 令 py为调用ToPrimitive的结果(y,Number)。
b. 设 px为调用ToPrimitive的结果(x,Number)。
3. 如果px和py都不是String类型,则
a. 令 nx为调用ToNumber(px)的结果。因为px和py是原始值,所以评估顺序并不重要。
b. 令 ny为调用ToNumber(py)的结果。
c. 如果 nx是NaN,则返回undefined。
d. 如果 ny是NaN,则返回undefined。
e. 如果 nx和ny是相同的Number值,则返回false。
f. 如果 nx为+0且ny为− 0,则返回false。
g. 如果 nx为− 0 且ny为+0,则返回false。
h. 如果 nx为+ ∞,则返回false。
i. 如果 ny为+ ∞,则返回true。
j. 如果 ny为-∞,则返回false。
k. 如果 nx为-∞,则返回true。
l. 如果nx的数学值小于ny的数学值(请注意,这些数学值都是有限的且不都是零),则返回true。否则,返回 false。
4. 否则,px和py都是字符串
a. 如果 py是px的前缀,则返回false。(如果q 可以是连接p和其他String r的结果,则String值p是String值q的前缀。请注意,任何String都是其自身的前缀,因为r 可能是空String。)
b. 如果 px是py的前缀,则返回true。
c. 令 k为最小的非负整数,以使px内的位置k处的字符不同于py内的位置k处的字符。(必须有一个k,因为String都不是另一个的前缀。)
d. 设m为整数,表示字符在px内位置k处的代码单位值。
e. 设n为整数,表示字符在py中位置k处的代码单位值。
f. 如果 m < n,则返回true。否则,返回 false。
按上述规范,对下列几个例子进行讲解:
1 | [] < []; //false |
1 | [] < {}; //ture |