4. 数据类型解读之 number、Symobol、BigInt
4.1 数字类型 number
- 整数、浮点数(小数)、正数、负数、零
- NaN: not a number 不是一个有效数字,但是它率属于number类型
typeof NaN => 'number'
- 出现场景:经常出现在,把其他类型转换为数字的时候,如果无法转换为有效数字,结果就是NaN
- NaN !== NaN NaN和任何值(包括自己本身),都不相等
- isNaN([val]):检测val是否“不是个有效数字”,如果不是 返回true, 如果是有效数字,返回false. 如果val不是数字类型的,浏览器首先会将其隐式转换为number类型,然后进行检测.
- Object.is(NaN, NaN) -> true ES6中提供的方法,不兼容IE浏览器
-
//let n = ? //if (n === NaN) { // 条件永远无法成立 // console.log('n不是有效数字') //} let n = ?; if(isNaN(n)){ console.log('n不是有效数字') } 复制代码
- Infinity 无穷大的值
4.2 Bigint
- Bigint 大数
- JS中最大/最小的安全数字:
Number.MAX_SAFE_INTEGER / Number.MIN_SAFE_INTEGER/Math.pow(2,53) - 1
9007199254740991 -9007199254740991 16位
- 超过这个范围的值进行数字运算,结果是不准确的
- 场景 服务器端存储的ID是一个很大的值【数据库我们可以基于longInt处理】,现在我们把这个值返回给客户端,客户端获取值之后,需要进行运算处理,如果超过安全数字,导致结果是不准确的.
Number.MAX_SAFE_INTEGER 9007199254740991 9007199254740991 + 10 9007199254741000 9007199254740991n + 10n 9007199254741001n typeof 9007199254741001n "bigint" Bigint("90071992547409919007199254740991") -> 90071992547409919007199254740991n //一个数字后面加“n”就是BigInt //计算完成的超长结果,基于toString转换为字符串【会去掉n】,把这个值再传递给服务器即可 复制代码
- JS中最大/最小的安全数字:
4.3 Symbol
- Symbol唯一值类型
Symbol() //创造一个唯一值 Symnol('xxx') //创造一个唯一值,只不过设置了标记
new Symbol() Uncaught TypeError: Symbol is not a constructor //不允许被new执行
- 用途1: 给对象设置一个唯一的属性【对象的成员只能是string & symbol 类型的值,Map允许属性名是不同类型的(包含对象)】
- 用途2:它是很多内置机制的实现方式
Symbol.toPrimitive
Symbol.hasInstance
Symbol.toStringTag
- …
-
console.log(Symbol('AA') === Symbol('AA')); //false 创造了两个唯一值 let sy = Symbol('AA') ys = sy sonsole.log(ys === sy) //true 只创建了一个唯一值 let key = Symbol('KEY') let obj = { //属性名:'name' 'age' '0' '1' Symbol() Symbol('KEY') '[object Object]' name:'zs', age:23, 0:100, 1:220, [Symbol()]:300, [key]:400, //把对象转换为字符串,去充当它的属性名 [{ name:'xxxx' }]:500 } console.log(obj[Symbol()]) //undefined 用新创建的唯一值去获取,肯定获取不到 console.log(obj[key]);//400 console.log(obj[0]);//100 -> obj['0'] 复制代码
5. 数据类型转换
5.1 把其他数据类型转换为number
Number([val])
- 一般用于浏览器的隐式转换中
- 规则:
- 把字符串转换为数字:空字符串变为0,如果出现任何一个非有效数字字符,结果都是NaN
- 把布尔值转换为数字 true -> 1 false -> 0
- null -> 0 undefined -> NaN
- Symbol无法转化为数字,会报错:Uncaught TypeError: Cannot convert a Symbol value to a number
- Bigint去除n(超过安全数字的,会按照科学计数法处理)
- 把对象转换为数字
- 先调用对象的Symbol.toPrimitive这个方法,如果不存在这个方法
- 再调用对象的valueOf获取原始值,如果获取的值不是原始值
- 再调用对象的toString把其变为字符串
- 最后再把字符串基于Number方法转换为数字
- parseInt([val],[radix])
- parseFloat([val])
- 一般用于手动转换
- 规则:[val]值必须是一个字符串,如果不是则先转换为字符串;然后从字符串左侧第一个字符开始找,把找到的有效数字字符最后转换为数字【一个都没找到就是NaN】;遇到一个非有效数字字符,不论后面是否还有有效数字字符,都不再查找了;parseFloat可以多识别一个小数点
let arr = [27.2, 0, '0013', '14px', 123]
arr = arr.map(parseInt)
/*
parseInt(27.2,0)
// 27.2 -> '272.2' -> '27' -> 把 '27' 看做10进制,转换为10进制 => 27
parseInt(0,1) => NaN
parseInt('0013', 2)
// '0013' -> '001' ->把'001'看做2进制,转换为10进制 => 1
0*2^2 + 0*2^1 + 1*2^0 = 1
parseInt('14px', 3)
// '14px' -> '1' -> 把'1'看做是3进制,转换为10进制 => 1
1 * 3^0
parseInt('123', 4)
// '123' -> 把'123'看做是4进制,转换为10进制 =>27
1*4^2 2*4^1 3*4^0
parseInt传递的第二个值是一个radix进制
+ radix不写或者写0,默认是10进制【如果第一个传递的字符串是以‘0x’开始的,那么默认是16进制】
+ radix取值范围:2~36,不在这个范围内,处理的结果都是NaN
+ 在传递的字符串中.从左到右,找到符合radix进制的值(遇到不符合的则结束查找),把找到的值,看做radix进制,最后转化为10进制
+ 把其它进制的值转换为10进制:‘按权展开求和’
*/
console.log(arr) // [27, NaN, 1, 1, 27]
复制代码
5.2 把其它类型转换为布尔
- 除了0/NaN/空字符串/null/undefined五个值是false,其余都是true
5.3 把其它类型转换为string
[val].toString() & String([val])
- 原始值类型:基于引号包起来,bigint会去掉n
- 对象类型的值:
- 调用Symbol.toPrimitive
- 如果不存在则继续调用valueOf获取原始值,有原始值则把其转换为字符串
- 如果不是原始值,则调用toString转换为字符串
- 特殊:普通对象转换为字符串是'[object Object]’ -> Object.prototype.toString
- “+”代表的字符串拼接
-
有两边,一边是字符串,则会变为字符串拼接
-
有两边, 一边是对象,按照Symbol.toPrimitive -> valueOf ->toString 处理,变为字符串后,就直接按照字符串拼接处理了
- 特殊情况:
{} + 10
-> 10 {}会被认为是代码块,处理的只是+10这个操作
- 特殊情况:
-
+只出现在左边 eg: +[val] 这是把val转换为数字 ++i(先累加在运算) & i++(先运算再累加)
-
let result = 100 + true + 21.2 + null + undefined + 'Tencent' + [] + null + 9 + false; // 100 + true + 21.2 + null 122.2 // 122.2 + undefined NaN // NaN + 'Tencent' 'NaNTencent' // 'NaNTencent' + [] + null + 9 + false 'NaNTencentnull9false' console.log(result) //'NaNTencentnull9false' 复制代码
-
5.4 ‘==’比较的时候相互转换的规则
- ‘==’ 相等,两边数据类型不同,需要转换为相同类型,然后进行比较
- 对象 == 字符串 对象转换为字符串 Symobol.toPrimitive -> valueOf -> toString
- null == undefined -> true null/undefined和其他任何值都不相等
null === undefined -> false
- 对象 == 对象 比较的是堆内存地址,地址相同则相等
- NaN !== NaN
- 除了以上情况,只要两边类型不一致,剩下的都是转换为数字,然后再进行比较
- ‘===’绝对相等,如果两边的类型不同,则直接是false,不会转换数据类型
- 上题目
console.log([] == false); //true
//[] -> Symbol.toPrimitive()/undefined valueOf()/[] toString/'' -> 0
// false -> 0 0 == 0 true
var a = ?
if (a == 1 && a == 2 && a == 3){
console.log('ok')
}
/*
'=='比较:数据类型转换的机制,需要把a转换为数字
因为把对象转换为数字,我们可以做的事很多 Symbol.toPrimitive -> valueOf -> toString -> Number
obj[Symbol.toPrimitive] = function(hint) {
// hint:number / string /default 浏览器自己调用这个方法的时候 会默认的实参值
}
var a = {
i:0,
//还可以重写valueOf和toString
[Symbol.toPrimitive](){
return ++this.i
}
}
---------
var a = [1, 2, 3]
a.toString = a.shift
全局上下文中
基于var声明的变量是给GO(window)设置的一个属性
获取属性a的值:Object.defineProperty进行数据劫持
var i = 0
Object.defineProperty(window, 'a', {
get(){
return ++i
}
})
*/
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END