一、数学运算符中的类型转换
1.减(-)乘(*)除(/)
在对非Number类型的运用数学运算符(- * / ),都会将非Number类型转成Number类型。
console.log(-true); //-1 true转为number类型为值为1,false为0
console.log(-null); // -0 null转为number类型为值为0
console.log(-undefined); // NaN undefined转为number类型为值为NaN
console.log(-"5"); // -5 数字字符串转为number类型为 相对应的值
console.log(-"null"); // NaN 非数字字符串转为number类型为NaN
console.log(-[5]); // -5 数组在转成number类型时经过了 先转成了String '5',在转成Number 5
console.log(-["5"]); // -5 数组在转成number类型时经过了 先转成了String '5',在转成Number 5
console.log(-[5, 3]); // NaN 数组在转成number类型时经过了 先转成了String '5,3',在转成Number NaN
console.log(-{ name: "zhangsan", age: 17 });//NaN 对象在转成number类型时经过了 先转成了String [Object Object] ,在转成Number NaN
上面的引用类型的转化在下面的引用对象的转化会讲。
2、特殊的加法(+)
为什么加法(+)是特殊的?因为JS中+还可以用来拼接字符串。有三个规则:
- 当一侧为String类型的,被识别为字符串拼接,并会优先将另一侧转换为字符串类型。
- 当一侧为(null、undefined、Boolean),则将这几个类型转化为Number类型。
- 当一侧为Number类型,另一侧为引用类型,将引用类型和
Number
类型转换成字符串后拼接。
// null boolean undefined
console.log(1 + true); //2 true转为number类型为值为1,false为0
console.log(1 + null); // 1 null转为number类型为值为0
console.log(1 + undefined); // NaN undefined转为number类型为值为NaN
// String
console.log(1 + "1233"); //11233 字符串拼接
// 引用类型
console.log(1 + [2]); //12 数组转为字符串后拼接
console.log(1 + [2, 3, 4]); //12,3,4
console.log(1 + { name: "zhangsan" }); //1[object Object] 对象转为字符串后拼接
以上 3 点,优先级从高到低,即 1+'1233'
会应用规则 1,而 1+true
会应用规则2。
二、有关==的隐式转换
1.undefined等于null
2.字符串和数字比较时,字符串转数字
3.数字和布尔比较时,布尔转数字
4.字符串和布尔比较时,两者转数字
// ==
undefined == null; //true
'0' == 0; //true,字符串转数字
0 == false; //true,布尔转数字
'0' == false; //true,两者转数字
三、比较运算符中隐式转化
1.有关===与==的区别
===恒等 的意思,不做类型转换,类型不同的结果一定不等。
// 如果类型不同,就一定不相等
console.log(123 === '123'); //false
// 如果两个都是数值,并且是同一个值,那么相等;如果其中至少一个是NaN,那么不相等。(判断一个值是否是NaN,只能使用isNaN() 来判断)
console.log(123 === 123); //true
console.log(123 === 10 / 'a'); //false
// 如果两个都是字符串,每个位置的字符都一样,那么相等,否则不相等。
console.log('hello' === 'hello'); //true
// 如果两个值都是true,或是false,那么相等
console.log(true === true); //true
console.log(1 === true); //false
// 如果两个值都是null,或是undefined,那么相等
console.log(null === null); //true
console.log(null === undefined); //false
==在做基本数据类型中会将类型转化后在比较。
对于Array,Object等高级类型,双等和三等是没有区别的 都是进行“指针地址”比较。
基础类型与高级类型,双等和三等是有区别的
- 对于==,将高级转化为基础类型,进行“值”比较
- 因为类型不同,===结果为false
2.'>' '<' '>=' '<=' 非数值的情况下使用
1、对于非数值进行比较时,会先将其转换为数值,然后再进行比较。
/ true转换为数值是1 false转换为数值是0
console.log(1 > true); // 结果为false
console.log(1 >= true); // 结果为true
console.log(1 > '0'); // 结果为true
console.log(1 > null); // 结果为true
//任何值和NaN作比较结果都是false
console.log(1 > 'hello'); // 结果为false 任何值和NaN作比较结果都是false
2 如果符号两侧都是字符串,不会将其转换为数值进行比较,而会分别比较字符串中字符的Unicode编码。
console.log('1' < '5'); // 结果为true
console.log('11' < '5'); // 结果也为true
console.log('be' > 'b'); // 结果为true 先比较第一位b的字符编码是一样的,再比较第二位,由于be有e,而b只有一位,所以be>b
console.log('be' < 'b'); // 结果为false
/*比较字符编码时,是一位一位进行比较的,
如果符号两侧第一位一样,则比较下一位,
所以借此可以用来对英文进行排序,而比较中文是没有意义的。*/
四、引用类型的隐式转换
基本类型间的比较相对简单。引用类型和基本类型的比较就相对复杂一些,先要把引用类型转成基本类型,再按上述的方法比较。
PreferredType转换策略
-
如果PreferredType被标记为Number,则会进行下面的操作流程来转换输入的值。
1、如果输入的值已经是一个原始值,则直接返回它
2、否则,如果输入的值是一个对象,则调用该对象的valueOf()方法, 如果valueOf()方法的返回值是一个原始值,则返回这个原始值。
3、否则,调用这个对象的toString()方法,如果toString()方法返回的是一个原始值,则返回这个原始值。
4、否则,抛出TypeError异常。
-
如果PreferredType被标记为String,则会进行下面的操作流程来转换输入的值。
1、如果输入的值已经是一个原始值,则直接返回它
2、否则,调用这个对象的toString()方法,如果toString()方法返回的是一个原始值,则返回这个原始值。
3、否则,如果输入的值是一个对象,则调用该对象的valueOf()方法, 如果valueOf()方法的返回值是一个原始值,则返回这个原始值。
4、否则,抛出TypeError异常。
注意:
PreferredType的值会按照这样的规则来自动设置:
1、该对象为Date类型,则PreferredType被设置为String
2、否则,PreferredType被设置为Number
例子:
[] + [] // ""
[1]+2 // 12
[]+[]进行ToPrimitive,两个都是Array对象,不是Date对象,所以以Number为转换标准,所以先调用valueOf(),结果还是[ ],不是原始值,所以继续调用toString(),结果是“”(空字符串)原始值,将“”返回。第二个[ ]过程是相同的,返回“”。加号两边结果都是String类型,所以进行字符串拼接,结果是“”。
[1]+2以Number为转换标准,所以先调用valueOf(),结果[1],不是原始值,所以继续调用toString(),结果是''1'',将“1”返回。加号一边结果是String类型,所以进行字符串拼接,结果是“12”。
[] + {} // "[object Object]"
进行ToPrimitive,依然是以Number为转换标准。 [ ]的结果是“”。 { }先调用valueOf(),结果是{ },不是原始值,所以继续调用toString(),结果是“[object Object]”,是原始值,将“[object Object]”返回。 加号两边结果都是String类型,所以进行字符串拼接,结果是“[object Object]”。