隐式类型转换

一、基本类型隐式转换:

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