JS笔记之JS数据类型(一)
JS笔记之JS数据类型(一)
原始类型的方法
在JS中允许我们像使用对象一样使用原始类型(数字。字符串等)。
1 字符串与对象的基本区别
一个原始值:
- 是原始类型中的一种值。
- 在 JavaScript 中有 7 种原始类型:
string
,number
,bigint
,boolean
,symbol
,null
和undefined
。
一个对象:
- 能够存储多个值作为属性。
- 可以使用大括号
{}
创建对象,例如:{name: "John", age: 30}
。JavaScript 中还有其他种类的对象,例如函数就是对象
1.1 如何解决使原始类型拥有和对象类似的方法?
- 原始类型仍然是原始的。与预期相同,提供单个值。
- JavaScript 允许访问字符串,数字,布尔值和 symbol 的方法和属性。
- 为了使它们起作用,创建了提供额外功能的特殊“对象包装器”,使用后即被销毁。
所以原始类型可以提供方法,但它们依然是轻量级的。
JavaScript 引擎高度优化了这个过程。它甚至可能跳过创建额外的对象。但是它仍然必须遵守规范,并且表现得好像它创建了一样。
null/undefined 没有任何方法
特殊的原始类型
null
和undefined
是例外。它们没有对应的“对象包装器”,也没有提供任何方法。从某种意义上说,它们是“最原始的”。尝试访问这种值的属性会导致错误:
alert(null.test); // error
2 数字类型
在现代的JS中数字有两种类型:
- JS中常规的数字以64为的格式存储,也称为双精度浮点数,是我们大多数使用时数字。但是不能安全地超过
(253-1)
或小于-(253-1)
。 - BigInt 表示任意长度的整数,仅在少数特殊领域才会用到 BigInt。
2.1 编写数字的方式
你如要写一个10亿的数字:let billion = 1000000000
也可以使用下划线作为分隔符 let billiion = 1_000_000_000
。
这里的下划线 _
扮演了“语法糖”的角色,使得数字具有更强的可读性。JS引擎会直接忽略数字之间的 _
,所以 上面两个例子其实是一样的。
在 JS 中,我们可以通过在数字后面附加字母 "e"
并指定零的个数来缩短数字:
1 | let billion = 1e9; // 10 亿,字面意思:数字 1 后面跟 9 个 0 |
换句话说,e
把数字乘以 1
后面跟着给定数量的 0 的数字。
1 | 1e3 === 1 * 1000; // e3 表示 *1000 |
现在让我们写一些非常小的数字。例如,1 微秒(百万分之一秒):
1 | let mcs = 0.000001; |
就像以前一样,可以使用 "e"
来完成。如果我们想避免显式地写零,我们可以这样写:
1 | let mcs = 1e-6; // 1 的左边有 6 个 0 |
2.2 十六进制、八进制和二进制数字
十六进制 在JS中总是表示颜色,使用0x
表示,二进制使用0b
表示,八进制使用0o
表示。只有这三种进制支持这种写法,其他的进制使用 parseInt 表示。
2.3 toString(base)
方法toString(base)方法,返回在给定base进制数字系统(base的范围可以从2到36。默认情况下是10)中num的字符串表示形式。
1 | let num= 255; |
常用的进制范例:
- base=16 用户十六进制颜色,字符编码等,数字可以是0..9 或者是A..F。
- base=2 主要用于调试按位操作。数字是0和1。
- base=36 是最大进制,数字可以是0..9或者A..Z,所有的字母都被用于表示数字,对于36进制来说、一个;例字设计:将一个较长的数字标识符转化较短的时候,比如短连接,可以使用基数为36的数字系统表示。
console.log( 123456..toString(36) ); // 2n9c
在范例第三点中
123456..toString(36)
两个点不是错误。如果想直接在一个数字上,调用一个方法,比如上面的例字中的toString,那么需要在数字后面加上两个点 .. 。如果放置一个点,
123456.toString(36)
那么就会出现一个error,因为JS语法隐含了第一个点后面的部分是小数部分,如果再放一个点,那么JS就知道小数部分为空。也可以写成
(123346).toString(36)
2.4 舍入
舍入是对数字比较常用的操作之一。一下是几个对数字进行舍入操作的内建函数。
Math.floor:向下舍入, 3.1 变成 3,-1.1 变成 -2。
Math.ceil:向下舍入,3.1 变成 4,-1.1 变成 -1。
Math.round:像最近的整数舍入。3.1 变成 3,3.6 变成 4,3.5 变成 4。
Math.trunc:(IE浏览器不支持)移除小数点后的内容而不舍入。3.1 变成 3,-1.1 变成 -1。
2.5 保留小数位数
toFixed(n) 将数字输入到下小数的后n位,以字符串的形式返回结果。会向上或者向下的舍入到近似的值,类似Math.round()。如果小数部分比需要的短,则在末尾加0。 可以使用一元符号或者Number()将其转化为数字。例如:+num.toFixed(5)
2.6 不精确的计算
数字内部是以64为存储数字的,所以:其中52位被用于存储这些数字,11为被存储与小数点的位置,一位用于符号,如果一个数字很大,可能会溢出64位存储,变成一个特殊的值:infinty。
1 | console.log(1e500); |
在大多数语言中都会有精度的问题,console.log( 0.1 + 0.2 ); // 0.30000000000000004
,
出现的原因:数字是以二进制存储在内存中,一个 1 和 0 的序列。但是在十进制数字系统中看起来很简单的 0.1
,0.2
这样的小数,实际上在二进制形式中是无限循环小数。
其中的解决办法有:
通过将数字舍入到最接近的可能数字来解决此问题,使用toFixed
+(0.1 + 0.2 ).toFixed(2)
使用乘法或者除法来减少误差。但是乘法除法只能减少误差,不能消除误差。
1
2alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3
alert( (0.28 * 100 + 0.14 * 100) / 100); // 0.4200000000000001实际上完全处理小数是不可能的,但是我们可以在满足条件的情况下,减掉尾巴,来进行四舍五入即可。
2.7 isFinite和isNaN
infinity和-infinity以及NaN 都属于Number类型,但不是普通的数字。
isNaN() 将参数转化为数字,并判断其是否为NaN。
为什么不用
xx === NaN
?因为在JS中,NaN是独一无二的,即使是NaN === NaN
进行比较也是false。isFinity() 将参数转为数字, 判断是否为常规数字。如果是常规数字而不是NaN、infinity,-infinity 返回true。
1
2
3console.log( isFinite("15") ); // true
console.log( isFinite("str") ); // false,因为是一个特殊的值:Na
console.log( isFinite(Infinity) ); // false,因为是一个特殊的值:Infinity请注意,在所有数字函数中,包括
isFinite
,空字符串或仅有空格的字符串均被视为0
。
与Object.is 进行比较。它类似于 === 一样对值进行比较,但是他对于两种边缘庆魁昂更可靠。
1.它适用于NaN:
Object.is(NaN, NaN) === true
。2.值0和-0是不同的,
Object.is(0, -0) === False
,从技术上讲是对的,因为在内部数字的符号位可能会不同,即使其他的均为0。在所有情况下,
Objet.is(a, b) 与 a === b
相同。
2.8 parseInt 和 parsrFloat
使用一元运算符将字符串转化为数字时,是严格的,当转化的字符串不是一个数字时就会失败。(除了字符开头结尾的空格)
1 | console.log(+"sss") // NaN |
在现实中我们会经常遇到带有单位的字符串, 100px, 100pt,19€(欧元)。
parseInt 和 parsrFloat 他们可以从字符串中提取数字,,直到无法读取为止,如果发生error则返回收集到的数字,函数parseInt 返回一个整数,parseFloat 返回一个浮点数。
1 | console.log( parseInt('100px') ); // 100 |
parseInt 和 parsrFloat 的局限性:只能是数字开头的字符串,如果第一个字符就不是数字则无法读取,返回NaN。
1 | console.log('xxx111') // NaN |
parseInt(str,radix) radix:技术的意思, 第二个参数制定了数字系统的基数,因此parseInt 还可以解析十六进制,八进制,二进制等字符串。
1 | alert( parseInt('0xff', 16) ); // 255 |
2.9 其他的数学函数
Math 对象包含了一个小型的数学函数和常量库。
- Math.random() 返回一个从 0 到 1 的随机数(不包括 1)。
- Math.max(a, b, c…) 和 Math.min(a, b, c…) 从任意数量的参数中返回最大值和最小值。
- Math.pow(n, power) 返回
n
的给定(power)次幂。
3 总结
要写很多0的数字
- 有很多0的整数,将e和0的个数写到数字的后面。
123e5 === 12300000
。 - 有很多0的小数,将e和0的个数写到数字的后面,0的个数前加上负号-,
1.33e-5 === 0.0000133
3.2 不同的数字系统
- 可以在十六进制,八进制,二进制 数字系统中写入数字。
- parseInt(str, base) 将字符串 str 解析为在给定的
base
数字系统中的整数,2 ≤ base ≤ 36
。 - num.toString(base) 将数字转化为给定的base数字系统中的字符串。
3.3 对于常规的数字检测
- isNaN(value) 将参数转为为数字,并判断是否为NaN。
- isFinite(value) 将其参数转换为数字,如果它是常规数字,则返回 true,而不是 `NaN/Infinity/-Infinity
3.4 将字符串转为数字
- 使用一元符号,但是是严格模式。
- 使用parseInt/parseFloat进行“软”转换,它从字符串中读取数字,然后返回在发生 error 前可以读取到的值。
3.5 小数
- 使用
Math.floor
,Math.ceil
,Math.trunc
,Math.round
或num.toFixed(precision)
进行舍入。 - 使用小数时损失精度。