数据类型数量
- js中数据类型一共8种,包含7种基本数据类型1种引用数据类型
- 原始数据类型:null undefined string boolean number bigint symbol
- 引用数据类型:object
存储方式
- 原始数据类型的值存储在栈内存中,不可以被修改也没有任何方法可以调用,大小固定,占用空间比较小
- 引用数据类型的指针存储在栈内存中,指针指向的值存储在堆内存中,大小不固定,一般占用空间比较大
原始数据类型为什么可以调用方法
- 调用方法时js已经进行数据类型隐式转换了,会将原始数据类型转换为对应的包装类(Null,Undefined,Bigint等),包装类可以调用方法
- 可以通过valueOf方法获取包装类的原始数据类型
- 可以通过new Boolean(true) 方式获取原始数据类型的包装类
判断数据类型的方式
-
typeof
- typeof可以判断原始数据类型中的undefined symbol bigint string number boolean和函数function
- typeof无法判断引用数据类型 结果都会返回object,由于原始数据类型null的存储地址和对象的地址相同所以也会返回object
-
Object.prototype.toString.call
- 可以判断所有的数据类型,返回格式为
[object Number]
其中的Nubmer为对应的数据类型
- 可以判断所有的数据类型,返回格式为
-
instanceof
- 可以判断所有的引用数据类型,不能判断原始数据类型,因为原理是基于原型链
- 原理:
- 简单概括就是在构造函数的原型链中去寻找是否存在该对象的原型
function myInstanceof (target, constructor) { const proto = Object.getPrototypeOf(target); let prototype = constructor.prototype; while (prototype) { if (proto === prototype) { return true } prototype = Object.getPrototypeOf(prototype) } return false }
-
constructor
- 判断引用数据类型,原理是对象可以通过隐式原型对象上的constructor属性访问构造函数
- 如果手动的改变了原型对象的指向,这种判断方式就不可以用了
-
通过隐式原型判断
Object.getPrototypeOf([1,2,3]) === Array.prototype // true
判断数组的方式
- instanceof
- Object.prototype.toString.call
- Array.isArray
- Array.prototype.isPrototypeOf
- Object.getPrototypeOf([1,2,3]) === Array.prototype
数据类型的转换
== 操作符 === 操作符 和Object.is()的区别
- == 区别于 === 的地方在于,== 如果两边数据类型不同会进行隐式数据类型的转换,而全等则会直接返回false
- Object.is和===主要有两点不同
Object.is(+0,-0) //false Object.is(NaN,NaN) // true
数据类型转换规则
原始数据类型的转换规则
-
数字和字符串
+
操作符会将数字转换为字符串进行字符串拼接- 其他运算会将字符串转为数字再运算,如果转换失败结果就是NaN
-
数字和布尔
- true转换为1 false转换为0
-
!运算符的转换
- 假值会转为false 其他值都会转换为true
- 假值包括(0,null,undefind,”,’false,NaN)
引用数据类型转为原始数据类型
- 每一个对象都有一个toPrimitive方法 用来转换原始数据类型
- 参数是个期望值,可以是number 或者是 string
- 会根据期望值的类型依次调用valueOf或者toString方法,如果第一个方法返回的结果是原始数据类型则直接返回该值,否则继续调用第二个方法,如果仍然不是原始数据类型则会报错
- 如果期望值是number则先调用valueOf方法 否则反之 一般只有Date的期望值是string其他的对象全是number
const obj = { [Symbol.toPrimitive](primitive) { let typeArr = ['null', 'undefined', 'boolean', 'symbol', 'bigint', 'string', 'number'] function myToString() { return 'toString' } function myValueOf() { return 'valueOf' } if (typeof primitive === 'string') { let res = myToString() if (typeArr.includes(typeof res)) { return res } else { res = myValueOf() if (typeArr.includes(typeof res)) { return res } else { throw new TypeError('类型转换失败') } } } else { let res = myValueOf() if (typeArr.includes(typeof res)) { return res } else { res = myToString() if (typeArr.includes(typeof res)) { return res } else { throw new TypeError('类型转换失败') } } } } } console.log(obj + 1) // toString1
BigInt
这个数据类型是es6新增的主要为了大数的计算,因为js中存在最大安全整数范围,Number.MAX_SAFE_INTEGER可以获取最大安全整数,超过这个范围计算的结果就会丢失精度,所以必须通过第三方库来解决这个问题,bigint的引入可以直接用原生js进行大数字的运算
一些面试题
-
null和undefined的区别
- null是空对象,undefined是未定义的值,typeof null会返回object,undefined不是保留字所以需要使用void 0 这种方式安全的获取undefined的值
-
0.1 + 0.2 === 0.3 为什么是false
- 因为js中存储数字的方式是通过IEEE754标准双精度浮点数,浮点数之间的运算会存在精度丢失的问题,所以不相等,
- 解决方案:
- 可以通过将左边的数转为整数再将结果转为小数
- 通过Number.EPLISON,这个数极小,只要两边结果之差小于这个数就认为相等
- 通过四舍五入
-
isNaN 和 Number.isNaN区别
- isNaN是Object的方法,如果值不是数字会进行数据类型转换再判断
- Number.isNaN会先判断数据类型,如果是数字并且值是NaN才会返回true
原文链接:https://juejin.cn/post/7255559160820334650 作者:芷茵