隐式类型转换
一、基本类型隐式转换:
1、转换成Boolean类型
- 可以转换成false的有:null,NaN,undefined,false,0,“”
- 其他的都会转换成 true
2、转换成Number类型
- String——>Number
- 数字字符串 ——>相应的数字
- 不是纯数字字符串——>NaN
- 空串——>0
- Boolean——>Number
- true——>1
- false——>0
- 其他
- null——>0
- undefined——>NaN
3、转换成String类型
- 都是直接加上引号
二、引用类型隐式转换
使用PreferredType转换策略:
PreferredType的值会按照这样的规则来自动设置:
1、该对象为Date类型,则PreferredType被设置为String
2、否则,PreferredType被设置为Number
如果PreferredType被标记为Number,则会进行下面的操作流程来转换输入的值。
1、如果输入的值已经是一个原始值,则直接返回它
2、否则,如果输入的值是一个对象,则调用该对象的valueOf()方法, 如果valueOf()方法的返回值是一个原始值,则返回这个原始值。
3、否则,调用这个对象的toString()方法,如果toString()方法返回的是一个原始值,则返回这个原始值。
4、否则,抛出TypeError异常。
如果PreferredType被标记为String,则会进行下面的操作流程来转换输入的值。
1、如果输入的值已经是一个原始值,则直接返回它
2、否则,调用这个对象的toString()方法,如果toString()方法返回的是一个原始值,则返回这个原始值。
3、否则,如果输入的值是一个对象,则调用该对象的valueOf()方法, 如果valueOf()方法的返回值是一个原始值,则返回这个原始值。
4、否则,抛出TypeError异常。
调用valueOf()返回的结果:
对象 | 返回值 |
---|---|
Array | 返回数组本身 |
Boolean | 布尔值 |
Date | 存储的时间是从1970年1月1日午夜开始级的毫秒数UTC,eg:(new Date()).valueOf() -->1660041962060 (相当于调用了getTime()) |
Function | 函数本身 |
Number | 数字值 |
Object | 对象本身(这是默认情况) |
String | 字符串 |
undefined、Null对象没有valueOf方法 |
调用toString()返回的结果:
对象 | 返回值 |
---|---|
Array | 以逗号分隔每个数组形成的字符串,约等于调用.join() |
Boolean | “true”或“false” |
Date | “Tue Aug 09 2022 18:45:16 GMT+0800 (GMT+08:00) ” |
Function | 函数的文本定义 |
Number | 数字转成的字符串如"123" |
Object | “[object Object]” ,特例:用new关键字加上内置对象创建的Object类型数据,调用toString。eg: (new String(‘abc’)).toString() ==> ‘abc’ (相当于先给他拍成对应的基础数据类型再调用toString方法) |
String | 字符串本身 |
[] + [] // ""
// 1.确定[] PreferredType 为number
// 2.确定[] 不是一个原始值
// 3.调用valueOf方法
// console.log([].valueOf(), typeof [].valueOf()); //结果是 [] object
// 4.调用toString()方法
// console.log([].valueOf().toString(), typeof [].valueOf().toString()); //结果是 '' string
// 5.最终 [] 隐式转换 => '' 空的字符串
[] + {} // "[object Object]"
//同样是按照上面的步骤,最后 {} 被隐式转换成字符串"[object object]"
//所以最终是 '' + '[object Object]' ,结果就是 "[object Object]"
{} + [] // 0
//js解释器会将开头的 {} 看作一个代码块,而不是一个js对象,所以{} + [] 会被解析成 {}; +[]
//所以最终是求 +[] 的值
{} + {} // "[object Object][object Object]"
//这里不同解析器下会得到不同的结果
//在金丝雀版本的chrome浏览器和node中,结果是"[object Object][object Object]"
//在普通版本的chrome浏览器中结果是 NaN
//这是为什么呢?原因是在node中会将以“{”开始,“}”结束的语句外面包裹一层( ),就变成了({} + {}),结果就是"[object Object][object Object]"
//而普通版本的chrome依然会解析成{};+{},结果就变成了NaN
三、操作符之间的隐式转换
1、二元运算符之间的隐式类型转换:
运算符 | 描述 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 取余 |
加法(+)
● 只有数字:直接相加
● 含有字符串:把其他的转换成字符串
● 没有字符串:都转成数字进行运算
console.log(1 + 1); //2
console.log(1 + 2 + 'hello'); //3hello
console.log(true + 'hello'); //truehello
console.log(true + undefined); //NaN
console.log(true + null); //1
● 含有引用类型的:引用类型隐式转换成字符串
console.log({} + 1) // "[object Object]1"
console.log([1,2,3] + true) //"1,2,3true"
减法(-)、乘法(*)、除法(/)、取余(%)
● 不是数字的都会转成数字再运算(引用类型先转成字符串再转成数字)
console.log(true * null); //0
console.log(true - 'hello'); //NaN
console.log({} - 1) // NaN
console.log([1,2,3] - true) //NaN
console.log([1] - true) //0
2、一元运算符
运算符 | 描述 |
---|---|
+ | 将操作数转换成数字,字符串的拼接 |
- | 将操作数转换成数字,同时变为负数 |
! | 逻辑取反运算符 |
++ | 递增 |
– | 递减 |
● 正、负号、++、-- 可以将变量转换成number类型
● 用 ’ ! ’ 将变量转换为Boolean类型
console.log(+"hello") //NaN
console.log(+"123") //123
console.log(!'hello') //false
var a = 'hello'
console.log(++a) //NaN
var b = true
console.log(++b) //2
3、比较运算符
返回值均为布尔值
运算符 | 描述 |
---|---|
== | 等于 |
=== | 值相等并且类型相等 |
!= | 不相等 |
!== | 值不相等或类型不相等 |
> | 大于 |
< | 小于 |
>= | 大于或等于 |
<= | 小于或等于 |
==
● 类型不同时,两边都转成number类型(引用类型先转成字符串再转成数字)
console.log(true == 'hello') //false
console.log('123' == 123) //true
console.log({} == 'hello') //false,相当于比较 NaN == NaN
● null、NaN、undefined类型和其他类型进行比较时,不做隐式类型转换,结果均为false,记住以下几个即可:
console.log(null == null) //true
console.log(undefined == undefined) //true
console.log(NaN == NaN) //false
console.log(undefined == null) //true
● NaN与其他比较都为false
!= 与 == 得出的结果相反,也是利用一样的规则
===和!==不做类型转换
>、<、>=、<=
● 非数值转成数值再比较
● 如果符号两侧都是字符串,不会将其转换为数值进行比较,而会分别比较字符串中字符的Unicode编码,而在比较字符编码时,是一位一位进行比较的,如果符号两侧第一位一样,则比较下一位
console.log('134545353' > '5'); // 不转型,返回false
console.log('134545353' > +'5');// 这样结果才返回true
4、逻辑运算符
运算符 | 描述 |
---|---|
&& | and |
|| | or |
! | not |
&& 和 ||
● 转成布尔值再进行逻辑运算,但是不一定返回布尔值
对于 &&:
1、当第一个表达式为真,整个表达式的结果取决于第二个表达式,返回第二个表达式
console.log('hello' && 'world'); //world
2、当第一个表达式为假,整个表达式的结果就可以确定,返回第一个表达式
console.log(false && 'world'); //false
console.log((10>15) && undefined) //false, (10>15)表达式本身返回的就是布尔值
console.log(null && 'world'); //null
对于||:
1、如果第一个操作数值为false,则返回第二个操作数。
console.log(null || 'hello'); //'hello'
console.log(null || false); //false
console.log(0 || null); //null
console.log(0 || (10>15)); //false
2、如果第一个操作数是真,直接返回第一个操作数。
console.log(123||345); //123
console.log((15>10) || 0); //true
强制类型转换
一、其他类型 => 字符串类型
1、toString()函数
null 和 undefined 没有 toString() 方法
var num = 10;
console.log(num.toString()); //"10"
console.log(num.toString(2)) //"1010" ,添加参数,表示转换成二进制再转成字符串
console.log(num.toString(8)) //"12" ,表示转换成八进制再转成字符串
console.log(num.toString(16)) //"a",表示转换成十六进制再转成字符串
2、 与空字符串相加
任意其他数据与字符串相加都会转化为字符串
console.log(typeof (true + '')); //string
二、其他类型 => 布尔类型
1、Boolean()包装器
Boolean('hello') //true
2、!!
!!'hello' //true
三、其他类型 => 数字类型
1、Number()包装器
如果转换的值是null,undefined,boolean,number
Number(true); //1
Number(false); //0
Number(null); //0
Number(undefined); //NaN
Number(10); //10 如果是数字值,原样输出
如果转换的值是string
Number("123"); //123 如果仅包含数值,转换为对应的数值
Number("234.1"); //234.1 解析为对应的小数
Number("+12.1"); //12.1 首位为符号位,其余为为数值,转换为对应的数值
Number("1+2.3"); // NaN 符号位出现在其他位置,解析为NaN
Number("0xa"); //10 如果仅包含十六进制格式,转为为对应的十进制的值
Number("010"); //10【注意】不会当做八进制被解析,结果为10。
Number(""); // 0 空字符串被转换为0
Number("123ac"); // NaN 包含其他字符: NaN
Number(12); //12
2、parseInt()函数
如果转换的值是null,undefined,boolean,均转换为NaN
如果转换的值是Number
parseInt(10); //10 如果是整数值,原样输出
parseInt(10.3); //10 如果是小数,舍去小数点以及后面的内容
如果转换的值是string
parseInt("123"); //123;如果仅包含数值,转换为对应的数值
parseInt("234.1"); //234;小数点后面的数值省略
parseInt("+12.1"); //12; 首位为符号位,其余为为数值,转换为整数
parseInt("1+2.7"); //1; 符号位出现在其他位置,保留符号位前面的数值
parseInt("0xa"); //10; 如果仅包含十六进制格式,转为为对应的十进制的值
parseInt("010"); //10; 【注意】不会当做八进制被解析,结果为10
parseInt(""); //NaN;空字符串被转换为NaN
parseInt("123ac"); //123;如果首位为数值,依次向后解析,找到连续的数值,直到遇到第一个非数值的,将之前获取的数值转换为Number返回 parseInt("123ac"); //123;
3、parseFloat()函数
如果转换的值是null,undefined,boolean,均转换为NaN
如果转换的值是Number
parseFloat(10); //10 如果是整数值,原样输出
parseFloat(10.1); //10.1 如果是小数,保留小数点,但是如果是10.0结果为10
如果转换的值是string
parseFloat("123"); //123;如果仅包含数值,转换为对应的数值
parseFloat("234.1"); //234.1;保留小数点后面的数值
parseFloat("+12.1"); //12.1; 首位为符号位,其余为为数值,转换为整数
parseFloat("1+2.6"); //1;符号位出现在其他位置,保留符号位前的数值
parseFloat("0xa"); //0; 【注意】不会当做十六进制来解析。
parseFloat("010"); //10; 【注意】不会当做八进制被解析,结果为10
parseFloat(""); //NaN;空字符串被转换为NaN
parseFloat("123.3ac"); //123.3;如果首位为数值,依次向后解析,找到连续的数值,直到遇到第一个非数值的,将之前获取的数值转换为Number返回 parseFloat("123.3ac");//123.3;
4、+
+"23" //23
+null //0
+undefined //NaN