文章内容为所看网课笔记,如有侵权请联系删除
## JS数据类型
1. 基本数据类型
number、string、undefined、null、boolean、symbol、bigint
2. 引用数据类型【对象类型】
(1) 标准普通对象: object
(2) 标准特殊对象: Array、RegExp、Date、Math、Error...
(3) 非标准特殊对象:Number、String、Boolean...
(4) 可调用对象/执行对象:function
## JS数据类型转换
1. 其他数据类型转换为数字型
方法一:Number([val]) 转换规则如下
(1) 字符串转换为数字:空字符串转为0,如果出现的是任何非有效数字字符,结果都是NaN
Number('') -> 0 Number('12c') -> NaN
(2) 布尔值转换为数字:true -> 1 , false -> 0
(3) null -> 0 , undefined -> NaN
(4) Symbol无法转换为数字,会报错:Uncaught TypeError: Cannot convert a Symbol value to a number
(5) BigInt去除'n'(超过安全数字的,会按照科学计数法处理)
Number(10n) -> 10
(6) 把对象转换为数字
a. 先调用对象的Symbol.toPrimitive方法,如果不存在该方法
【如果有该方法,这个值的Symbol.toPrimitive方法返回什么,则结果就是什么】
【Symbol.toPrimitive(参数) :参数为要转换的数据类型:分别为number、string、default【意思为不确定要转换为什么数据类型】】
b. 在调用对象的valueOf获取原始值,如果获取的值不是原始值
【任何一个对象都有valueOf方法,即便这个对象上没有也会通过原型链找到Object对象的原型上的valueOf】
【valueOf方法用来获取原始值,数组的原始值还是数组】
c. 在调用对象的toString 将其转换为字符串
d. 最后在把字符串基于Number方法转换为数字
方法二:parseInt([val],[radix]) 规则如下
(1) parseInt([val],[radix])说明
a. [val]值必须是一个字符串,如果不是先隐式转换为字符串【通过String([val])转换】
b. [radix]进制
--如果不写,或者写0:默认是10进制【特殊情况:如果字符串是以0x开始的,默认是16进制】
--有效范围:2~36之间【如果不在这个区间,结果直接是NaN】
2进制:01
3进制:012
8进制:0~7
10进制:0~9
16进制:0~9 A~F
36进制:0~9 A~Z
(2) 转换规则如下
a. [val]值必须是一个字符串,如果不是先隐式转换为字符串【通过String([val])转换】
b. 然后从字符串左侧的第一个字符开始寻找,查找出符合[radix]进制的值【遇到不符合的就结 束查找,不论后面是否还有符合的】
parseInt('12px13',2) -> 1
parseInt('10102px13',2) -> 1010【二进制】 ->10【十进制】
c. 把找到的内容,按照[radix]进制转换为10进制的数字【一个都没找到就是NaN】
d. 遇到一个非有效数字字符,不论后面是否是有效数字字符,都不在查找了
方法三:parseFloat([val])
(1) 转换规则如下
a. [val]必须是一个字符串,如果不是,就要隐式转换为字符串
b. 然后从字符串左侧的第一个字符串开始寻找,把找到的有效数字字符最后转换为数字【一个都没找到就是NaN】
c. 遇到一个非有效数字字符,不论后面是否是有效数字字符,都不在查找了
d. parseFloat可以多识别一个小数点
例题
let arr = [27.2,0,'0013','14px',123]
arr = arr.map(parseInt)
console.log(arr) //[27,NaN,1,1,27]
// 解析
// arr.map((item,index){return item*10})方法:迭代数组的每一项,并对其进行修改【原始数组不变,返回新数组】【参数是一个函数】
// arr.map(parseInt)相当于把parseInt方法作为参数,然后原数组中的item和index作为parseInt方法的参数
// parseInt(27.2,0) -> parseInt('27.2',10) -> 27【十进制】
// parseInt(0,1) -> NaN
// parseInt('0013',2) -> 001【二进制】 -> 1【十进制】
// parseInt('14px',3) -> 1【3进制】 -> 1【十进制】
// parseInt(123,4) -> 123【4进制】 -> 27【十进制】
// parseInt(0013,2) -> parseInt(11,2) -> parseInt('11',2) ->11【二进制】-> 3【十进制】 【先将0013按照8进制转为10进制的数字11】
// JS遇到以0开始的“数字”,会默认将其按照8进制转为10进制,然后在进行其他操作
2. 其他数据类型转换为字符串
方法一:默认使用String([val])方法
规则如下
(1) 若val是一个原始值,则转换结果直接包裹括号即可
【特殊情况 String({}) //'[object Object]'】
(2) 若val是一个对象,转换规则如下
a. 先调用对象的Symbol.toPrimitive方法,
b. 如果没有Symbol.toPrimitive方法,在调用对象的indexOf,获取原始值
【每个对象都有indexOf方法,即便它本身没有,但可以通过原型链访问到Object的原型上的indexOf方法】
【数组的原始值还是数组】
c. 如果获取的原始值不是基本数据类型,则调用对象的toString方法将其转换为字符串
方法二:"+"出现字符串拼接的情况
(1) "+"两边,一边是字符串
(2) "+"两边,一边是对象
(3) "+"出现在值的左侧,除了字符串拼接的情况,而且该值会转换为数字
let i ='10'
console.log(+i) //10
注意:String([val])和val.toString()的结果不一样
(1) String([val])的结果除了是字符串外,也可以是别的类型;val.toString()的结果只能是字符串
3. 其他数据类型转换为布尔值
(1) 转换规则
a. 除0、NaN、空字符串、null、undefined返回的值是false外,其余都是true
4. "=="比较时的相互转换规则
"==" :两边数据类型不同,需要先转换为相同的类型,然后在进行比较
(1) 对象==字符串,对象转字符串【Symbol.toPrimitive -> valueOf -> toString】
(2) null == undefined -> true null/undefined和其他任何值都不相同
null === undefined -> false
应用场景
function(num){
if(num==null){这里说明num为undefined或者null}
}
(3) 对象==对象 比较的是内存地址,地址相同则相等
(4) NaN !== NaN true
NaN == NaN false
Object.is(NaN,NaN) true
(5) 除了以上情况,只要两边类型不一致,剩下的都是转换为数字,然后在进行比较
console.log([] == false) //true 两边都转换为数字
console.log(![] == false) //true 先处理![] -> false false == false -> true
"===": 如果两边类型不同,直接返回false,不会发生数据类型转换
## JS装箱和拆箱
1. 装箱操作:把原始值变为非标准特殊对象
let num = 10
console.log(num.toFixed(2)) //10.00
// toFixed(n)方法 :小数点后保留n位小数
// num是原始值,不是一个对象,按照常理来说,是不能进行“成员访问”的
// 默认装箱操作:new Number(num)变为非标准特殊对象,这样就可以调用 toFixed(n)方法了
2. 拆箱操作:把非标准特殊对象变为原始值
let num = new Number(10)
console.log(num+10) //20
// 在操作的过程中,浏览器会把num这个非标准特殊对象变为原始值【Symbol.toPrimitive-> valueOf...】,这个操作叫做拆箱
3. 装箱和拆箱都是浏览器默认数据类型隐式转换的过程