一. 原始值包装类型
在 JS 中,原始值(基本数据)类型是没有属性和方法的,但是为便于操作基本数据类型,ES 提供了三种特殊的引用类型 ----- 原始值包装类型。
Boolean 、Number 、String。即它们仨是在它们原来的基础上进行包装,给它们赋予一些属性和方法!!!
每当使用到原始值的方法或属性时,后台都会创建一个相应的原始值包装类型的对象,步骤如下:
- 创建对应原始值包装类型的对象
- 调用相关方法 or 属性(length)
- 立马销毁对象
let a = "abc";
console.log(a.length); // 执行到改行时,JS 会把 "abc"在后台转换为 String("abc"),
然后访问其身上的 length 属性,然后执行完改行后,会立马把 String("abc") 对象销毁!!!!
装箱 && 拆箱:
装箱JS 也可以通过 Object() 函数显式地把基本类型转换为包装类型!!!
拆箱也可以使用 valueOf() 方法把包装类型转换为基本类型。在引用类型对象上调用该方法,会返回它的原始值类型,如果没有,就返回该对象本身!!!!
!!!注意:
原始值包装类型的实例对象的声明周期只存在于访问它的那行代码期间 ,所以不可以给原始值包装类型的对象添加属性!!
二. 隐式类型转换规则
JS 中的隐式类型转换一般发生在
+ - * /以及== > < !操作符之间。而这些操作符只能操作原始值类型,所以如果有对象,就会先调用 valueOf() 方法,如果返回的是原始值类型,就直接返回,如果不是,就接着调用 toString() 方法!!!
不同的运算符有不同的转换规则:
<1>+ 加 【主 string】
-
类型一样直接加
- string + string - number + number -
string + number 都转换为 string 类型!!
- string + number ===> string + string -
其余类型:boolean、null、undefined 转换为 string
-
如果有对象,就调用对象身上的 toString() 方法将其转化为字符串,再按照字符串进行 + 运算!!!
<2>- * / 减乘除 【主 number】
- 两边的值都会被转换为 number 类型,然后进行运算!!
- 对象会先 valueOf() ,然后 toString(), 最后Number()
注意: NaN 也是 number 类型,任何涉及 NaN 的运算,返回值都为 NaN!!
<3>>= <= 比较 【主 number】
-
string > string 不用进行转换,直接按顺序一个一个字符比较 ASCII 码的值即可!!!
-
boolean 直接转换为 number
- true ----> 1 - false ----> 0 -
string > number ===> number > number
-
如果有对象,就先 valueOf() ,不行再 toString() !!
- 然后再根据前面的规则进行比较!!
<4>== != === !== 相等操作符
(1) != 和 == 会进行类型转换 【主 number】
-
boolean 直接转换为 number
- true ----> 1 - false ----> 0 -
string == number ---> number == number
-
如果有对象,先 valueOf() ,不行再 toString()
- 然后再根据前面的规则进行比较!! -
遇见 NaN ,就返回 false!!
(2) !== 和 === 不会进行类型转换
- 类型不一样就直接返回 false
栗子:
var a = {};
a > 2 // false
// 其中涉及的隐式转换过程如下:
先对 > 操作符两边的值调用ToPrimitive()方法,都转换为原始值类型。
- 对于 {} ,先调用 {}.valuef() ,由于{}不存在与之对应的原始值类型(即没法拆箱),
所以就会返回该对象本身,即{}
- 然后再调用 {}.toString() 方法,由于 {} 是 Object 的实例,所以此处的 toString() 方法,
就是Object原型上的toString()方法(没有经过重写的),所以就会返回字符串"[object Object]"
而 "[object Object]" > 2
- > 操作符 主 number ,所以把"[object Object]"转换为 number 类型为 NaN
- NaN > 2 // false
对于 toString() 方法:
console.log({1:1}.toString())
console.log([1,2].toString())
console.log(new Date().toString())
看有没有重写该方法了!!!