本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
由于 JS 是一门弱类型或者说是动态语言。变量没有类型限制,可以随时赋予任意值。所以在 JS 定义的数据类型是不确定的,但是但是各种运算符对数据类型是有要求的。如果运算符发现,运算值的类型与预期不符,就会自动进行转换类型。
原始类型之间的转换
在ES5中定义的只要原始类型主要有‘字符串(String)’,‘数字(Number)’,‘布尔值(Boolean)’,undifined和Null,其中类型转换主要有原始类型转布尔,数字,字符串三种。
let str = 'hello'
let num = 0
let bool = false
let un = undefined
let nu = null
//原始值转布尔
console.log(Boolean(str)); // false
console.log(Boolean(num)); // 0 false 其他为 ture
console.log(Boolean(bool)); //false
console.log(Boolean(un)); //false
console.log(Boolean(nu)); //fasle
console.log(Boolean(NaN)); //fasle
//原始值转数字
console.log(Number()); // 0
console.log(Number(str)); // NaN
console.log(Number(bool)); // 0
console.log(Number(undefined)); // NaN
console.log(Number(nu)); // 0
//原始值转字符串
console.log(String(num)); // -1
console.log(String(bool)); // false
console.log(String(un)); // undefined
console.log(String(NaN)); // NaN
console.log(String(Infinity)); // Infinity
原始类型转对象
原始类型得转换不仅仅停留在原始值之间的转换,还有原始类型和对象之间的转换。
//原始值转对象
// String() Number() Boolean()
let a = 1 || '1' true
console.log(typeof a); // number
let b = new Number(a)
console.log(typeof b); // object
对象转原始类型
既然存在原始类型转对象,那就必然也有对象转原始类型。
// 对象转原始类型
//对象转布尔
console.log(Boolean([])); //所有引用类型转对象都为 true
//对象转数字和字符串
// toString() valueOf() 对象转字符串和数字的方法
Object.prototype.toString.call({a: 1}) // '[object Object]'
let s = new String('hello') //用String去new一个字符串
console.log(s); //打印出String {'hello'} 对象
let obj = {"a": 1}
let a = JSON.stringify(obj) //对象转字符串
JSON.parse(a) // 字符串转对象
对象转原始类型一定会调用ToPrimitive(obj,Number/String)方法, ToPrimitive(input,PreferredType), PreferredType不存在时,默认为String,input是Date类型,相当于PreferredType==String
ToPrimitive(obj, Number)
- 如果obj是基本类型,直接返回
- 否则,调用valueOf(取原始值) 方法,如果得到一个原始类型,则返回
- 否则,调用toString 方法,如果得到一个原始类型,则返回
- 否则报错
ToPrimitive(obj, String)
- 如果obj是基本类型,直接返回
- 否则,调用toString 方法,如果得到一个原始类型,则返回
- 否则,调用valueOf 方法,如果得到一个原始类型,则返回
- 否则报错
String({name:'duck'}) //'[object Object]'
//执行过程
//({name:'duck'}).toString()//'[object Object]'
//String('[object Object]')=>'[object Object]'
Number({})//NaN
//执行过程
//({}).valueOf()//{}
//({}).toString()//'[object Object]'
//Number('[object Object]')=>NaN
Number([])//0
隐式类型转换
一元运算符
v1
当 - 运算作为一元操作符时,会调用ToNumber()处理该值(非Number类型的值),转不了的变为NaN
当 + 运算作为一元操作符时,会调用ToNumber()处理该值(非Number类型的值),转不了的变为NaN
1 + '1' //'11'
[] == ![] // ture ![] == false == 0
[] == [] // false 数组的引用地址不一样
[] + [] // ''
[] + {} // '[object Object]'
{} + [] // 0 == + []
二元操作符
v1 + v2 (都往数字身上转,遇到字符串转字符串)
- lprim = Toprimitive(v1)
- rprim = Toprimitive(v2)
- 如果lprim 或者 rprim 是字符串 那么返回 ToString(lprim) 和 ToString(rprim)的拼接结果
- 返回ToNumber(lprim) 和 ToNumber(rprim) 的相加结果
1 + '1' //'11'
null + 1 // 1
[] + [] // ''
[] + {} // '[object Object]'
{} + [] // 0 == { }//代码块 + []
({} + []) // '[object Object]'
{} + {} // '[object Object][object Object]'
二元运算符
如果x和y是同一类型:
1.x是undefined,返回true
2.x是null,返回true
3.x是数字,x为NaN,返回false
4.x和y指向同一个对象(内存地址),返回true,否则返回false
let x={};
let y=x;
x==y // true
{}=={} // false
[]==[] // false
undifined == undifined // true
null == null // true
1 == NaN // false
NaN == NaN // false
如果x和y不是同一类型
1.null==undefined =>true
2.x是String类型,ToNumber(x)
3.x是Boolean类型,ToNumber(x)
4.x不是String/Number,y是Object true=={a:123} //false
null == undifined // true
'1' == 1 // ture
ture == '1' // ture
ture == 1 // ture
ture == {} // flase
false == {} //flase