“这是我参与更文挑战的第4天,活动详情查看: 更文挑战”
#js的数据类型分类
-
基本数据类型
- number
- string
- boolean
- null
- undefined
- symbol
1.static.Symbol
2.Symbol.prototype -
引用数据类型
- object
1.普通对象
2.数组对象
3.正则对象
4.日期对象
5.JSON对象
6.Set
7.Map
- object
-
函数
1.普通函数
2.构造函数
3.箭头函数
4.生成器函数
##首先我们先来说一下number类型
number类型包括的是正数 0 负数 小数,还有一个NaN(非数字)
typeof (NaN) // number
复制代码
然后需要注意的是NaN!=NaN,因此当我们执行下面的判断是不会生效的。
let value = NaN; //注意这个NaN一般是经过转化之后得到的比如说 Number('string')
if(value==NaN){
// operate sth
}
复制代码
那这样我们怎么去判断一个变量的value是不是NaN的值呢?
有两种方法:
第一种:
let value = NaN;
isNaN(value)// true
复制代码
第二种方法是通过Object.is()
object.is(NaN, NaN) // Object.is(),是判断两个值是否相等的 ,如果是对象的话那么就是判断两个对象是不是共用一个存储空间
复制代码
由于NaN一般是经过转化获取的 , 所以我们来讲一下如果将其他数据类型转化成number类型
显示转化 有下面几种方法
let a ='String'
// (1) Number()
Number(a)
// (2) parseInt()/ parseFloat()
parseInt(a)
复制代码
需要注意注意的是这集中方法虽然都可以将其他数据类型转化成number类型的,但是他们的转化规则和机制都是不相同的。
首先说一下Number转换
如果是boolean,那么true 和false会被分别转换成1, 0 。
null → 0
undefined→ NaN
如果是字符串的话:
(1)如果字符串是‘’, 那么会被转化成0;
(2)如果字符串前面包含空格,会去掉空格进行转换
let str =' 11111';
Number(str)//1111
复制代码
(3)字符串包含有效地十六进制, 如’0xf’, 那么会转化为相大小的十进制
let str ='0xf'
Number(str)// 15
复制代码
(4)字符串前面有0的话,会忽略前面的0,进行转换
let str ="000033333"
Number(str) //33333
复制代码
(5)数字中混入其他非数字,那么都会被转化成NaN
let str ='1111 ddd'
Number(str) // NaN
let str1 ='ddd1111 '
Number(str1) // NaN
复制代码
对于parseInt的转换规则主要是:
(1)如果是数字开头的话, 会一直解析到遇到非数字的character停止, 如果是小数比如1.1,那么会解析到小数点前面的, 返回1
parseInt('11111dddddd222222') //11111
复制代码
(2)如果字符串前面包含空格,会去掉空格进行转换。
parseInt(' 11111dddddd222222') //11111
复制代码
(3)其他情况都会被转化为NaN
parseInt(true)// NaN;
parseInt('ddddd111111')//NaN
复制代码
(4)使用parseInt的时候还可以把二进制把金卮十六进制或者其他任何禁止的字符串转化成整数
var num1 = parseInt("AF",16); //175
var num2 = parseInt("AF"); //NaN
var num3 = parseInt("10",2); //2 (按照二进制解析)
var num4 = parseInt("sdasdad"); //NaN
复制代码
parseFloat()与parseInt转换规则类似, 不一样的地方是 , 他不能转化成对应的进制
并且他遇到小数点的话可以继续解析 。
隐式转换
主要有三种,
(1)+ (1+true)
(2) == 比较的时候
(3) isNaN() 也会先进行转化成数字在进行比较
##String类型
(1)””,
(2)“
把其他类型的值转化成String类型。
显式转换
(1) toString()
(2)String()
隐式转换
(1)+加号除了数学运算还可以拼接字符串 。
下面我们来说下加号的拼接规则。
(1)如果加号两边, 其中一边出现了字符串的话 , 那么会出现拼接字符串 。
let n = 10
let res = n + '10' // 1010
复制代码
(2) 加号两边, 其中一边是一个对象的话 ,则也可能成为字符串拼接
_ 对象出现在右边
let m = 10
let res = m + {} // "10[object Object]"
复制代码
_ 对象处在左边
{} + 10 // 10 像这种不加上括号的, 浏览器会认为前面的对象是一个代码块 , 不参与运算的 , 所以返回的时候后面的数字
({} + 10 ) // "[object Object]10" // 这里浏览器会认为这个{}参与运算, 所以返回的是字符串拼接
复制代码
_ 对象 是new Number类型的 , new Nnumber会转化成Number类型的来计算
let m = 10,
let obj = new Number(10)
obj+ m // 20
复制代码
_对象里面属性中含有的是value的属性
let test = {
value: 10
}
test+ 10 // "[object Object]10"
复制代码
看了上面的例子, 那如果加号的一边是对象计算底层机制是什么呢 ?
检测对象的 Symbol.toPrimitive的属性是否存在, 如果是存在的话,基于这个值进行计算, 如果没有话 ,
检测对象的valueOf(), 如果这个值是基本类型值 的话, 则基于这个值来计算 , 如果这个值不是基本类型值的话,获取对象的toString(), 然后进行拼接。
例如我们写一个 对象含有Symbol.primitive属性:
let obj ={
[Symbol.toPrimitive]: function (){
return 10
}
}
obj+ 10 // 20
复制代码
然后我们的new Number(10) + 10 之所以为20 是因为 new Number(10).valueOf()//10, 所以可以直接计算 。
其他转化成字符串的就是通过了toString()
(3)如果加号之后只有一边, 如果是字符串的话就会被转换成数字
let m = '10'
console.log(+m) // 10
console.log(++m) // 11
复制代码
##Symbol类型
这种 类型的作用是创建唯一值。
(1)给对象设置一个Symbol属性, 这是一个唯一属性来减少属性上面的冲突 。
例如给一个对象创造唯一属性 我们可以使用
let obj = {
[Symbol()]: '11111'
}
obj[Symbol] // undefined
复制代码
但是我们不能够拿出这个唯一属性的值 , 所以我们可以事先 定义一个变量名叫 x
let x = Symbol()
let obj = {
[x]: 1
}
obj[x] // 1
复制代码
(2)来宏观管理一些唯一标识的时候,也是用的唯一值。比如说上面的Symbol.toPrimiteve。类似的还有
Symbol.hasInstance、 Symbol.toStringTag()、Symbol.iterator
需要注意的是 : Symbol是一个构造函数, 但是我们不能使用new Symbol()来创建 ,并且 两个Symbol是不相同的
Symbol('a') ===Symbol('a') // false
复制代码
##BigInt类型
大数类型 主要是用来解决当数字超过Number.MAX_SAFE_INTEGER, 或者是 Number.MIN_SAFE_INTEGER, 发生溢出, 导致计算错误的问题的 。
let a = Number.MAX_SAFE_INTEGER // 9007199254740991
a+ 10 // 9007199254741000
//尾数应该是1, 但是现在的结果还是 0, 所以说是有问题的 , 我们可以利用大数类型来解决的
复制代码
首先说下 如何创建BigInt类型,
第一种是直接BigInt(10)
第二种是 10n, 后面直接加上n
let b = BigInt(9007199254740991)
let d = 10n
b +d //9007199254741001n
复制代码