数字类型
JavaScript 中数字有两种类型
- 双精度浮点数,也就是我们常用的数字
- BigInt 数字。因为常规数字不能超过
2^53
或者小于-2^53
。所以退出了 BigInt 的类型。
使用 Obejct.is 判断 NaN
1 | Object.is(NaN, NaN); // true |
Object.is
类似于执行 ===
的相等判断。但是对于两种边缘情况更可靠
1 | Object.is(0, -0); // false |
字符串
push、pop、shift、unshift
push/pop
方法运行的比较快,而 shift/unshift
比较慢。
这个有点像是堆栈,push和pop都是操作栈顶的元素,所以快。
数组的方法
- push、pop、shift、unshift
- splice
- slice
- concat
- forEach、map
- indexOf、lastIndexOf、includes
- find、findIndex
- filter
- sort、reverse
- split、join
- reduce、reduceRight
- Array.isArray
迭代
使用 for...of
进行迭代
Symbol.iterator
使用 Symbol.iterator
给对象添加可迭代功能
1 | let range = { |
- 当
for..of
循环启动时,它会调用这个方法(如果没找到,就会报错)。这个方法必须返回一个 迭代器(iterator) —— 一个有next
方法的对象。 - 从此开始,
for..of
仅适用于这个被返回的对象。 - 当
for..of
循环希望取得下一个数值,它就调用这个对象的next()
方法。 next()
方法返回的结果的格式必须是{done: Boolean, value: any}
,当done=true
时,表示迭代结束,否则value
是下一个值。
完整实现:
1 | let range = { |
range
自身没有next()
方法。- 相反,是通过调用
range[Symbol.iterator]()
创建了另一个对象,即所谓的“迭代器”对象,并且它的next
会为迭代生成值。
字符串的迭代
1 | for (let char of "test") { |
显示的调用迭代器
也是直接获取了 Symbol.iterator
1 | let str = "Hello"; |
可以应用 for..of
的对象被称为 可迭代的。
- 技术上来说,可迭代对象必须实现
Symbol.iterator
方法。obj[Symbol.iterator]()
的结果被称为 迭代器(iterator)。由它处理进一步的迭代过程。- 一个迭代器必须有
next()
方法,它返回一个{done: Boolean, value: any}
对象,这里done:true
表明迭代结束,否则value
就是下一个值。
Symbol.iterator
方法会被for..of
自动调用,但我们也可以直接调用它。- 内置的可迭代对象例如字符串和数组,都实现了
Symbol.iterator
。 - 字符串迭代器能够识别代理对(surrogate pair)。(译注:代理对也就是 UTF-16 扩展字符。)
有索引属性和 length
属性的对象被称为 类数组对象。这种对象可能还具有其他属性和方法,但是没有数组的内建方法。如下
1 | let arrayLike = { |
如果我们仔细研究一下规范 —— 就会发现大多数内建方法都假设它们需要处理的是可迭代对象或者类数组对象,而不是“真正的”数组,因为这样抽象度更高。
Array.from(obj[, mapFn, thisArg])
将可迭代对象或类数组对象 obj
转化为真正的数组 Array
,然后我们就可以对它应用数组的方法。可选参数 mapFn
和 thisArg
允许我们将函数应用到每个元素。
Map 和 Set (映射和集合)
Map
Map 是一个带键的数据项的集合,就像一个 Object
一样。 但是它们最大的差别是 Map
允许任何类型的键(key)。
它的方法和属性如下:
new Map()
—— 创建 map。map.set(key, value)
—— 根据键存储值。map.get(key)
—— 根据键来返回值,如果map
中不存在对应的key
,则返回undefined
。map.has(key)
—— 如果key
存在则返回true
,否则返回false
。map.delete(key)
—— 删除指定键的值。map.clear()
—— 清空 map。map.size
—— 返回当前元素个数。
举个🌰
1 | let map = new Map(); |
Map 的键,可以是任何类型。
和可以是对象
1 | let john = { name: "John" }; |
map.set
调用返回map自身,可以“链式”调用
1 | map.set('1', 'str1') |
Map 迭代
如果要在 map
里使用循环,可以使用以下三个方法:
map.keys()
—— 遍历并返回所有的键(returns an iterable for keys),map.values()
—— 遍历并返回所有的值(returns an iterable for values),map.entries()
—— 遍历并返回所有的实体(returns an iterable for entries)[key, value]
,for..of
在默认情况下使用的就是这个。
这个有点像是对象中的那三个方法。
Map 与 Object 的转换
Object to Map
Object.entries
1 | let obj = { |
Map to Object
Object.fromEntries
1 | let prices = Object.fromEntries([ |
Set
Set
是一个特殊的类型集合 —— “值的集合”(没有键),它的每一个值只能出现一次。
它的主要方法如下:
new Set(iterable)
—— 创建一个set
,如果提供了一个iterable
对象(通常是数组),将会从数组里面复制值到set
中。set.add(value)
—— 添加一个值,返回 set 本身set.delete(value)
—— 删除值,如果value
在这个方法调用的时候存在则返回true
,否则返回false
。set.has(value)
—— 如果value
在 set 中,返回true
,否则返回false
。set.clear()
—— 清空 set。set.size
—— 返回元素个数。
因为 Set
的每个值只能出现一次,所以,可以用来进行数组去重。
可以使用 for..of
或 forEach
来遍历 Set:
Map
中用于迭代的方法在 Set
中也同样支持:
set.keys()
—— 遍历并返回所有的值(returns an iterable object for values),set.values()
—— 与set.keys()
作用相同,这是为了兼容Map
,set.entries()
—— 遍历并返回所有的实体(returns an iterable object for entries)[value, value]
,它的存在也是为了兼容Map
WeakMap and WeakSet(弱映射和弱集合)
Map使用对象作为键,不会被垃圾回收机制回收
1 | let john = { name: "John" }; |
WeakMap
WeakMap
和 Map
的第一个不同点就是,WeakMap
的键必须是对象,不能是原始值,而且可以被垃圾回收机制回收。
1 | let weakMap = new WeakMap(); |
现在,如果我们在 weakMap 中使用一个对象作为键,并且没有其他对这个对象的引用 —— 该对象将会被从内存(和map)中自动清除。
1 | let john = { name: "John" }; |
WeakMap
不支持迭代以及 keys()
,values()
和 entries()
方法。所以没有办法获取 WeakMap
的所有键或值。
WeakMap
只有以下的方法:
weakMap.get(key)
weakMap.set(key, value)
weakMap.delete(key)
weakMap.has(key)
WeakMap
可以用来管理缓存
1 | // 📁 cache.js |
WeakSet
WeakSet
的表现类似:
- 与
Set
类似,但是我们只能向WeakSet
添加对象(而不能是原始值)。 - 对象只有在其它某个(些)地方能被访问的时候,才能留在 set 中。
- 跟
Set
一样,WeakSet
支持add
,has
和delete
方法,但不支持size
和keys()
,并且不可迭代。
结构复制
数组中不想要的元素也可以通过添加额外的逗号来把它丢弃:
1 | // 不需要第二个元素 |
我们可以将其与任何可迭代对象一起使用,而不仅限于数组:
1 | let [a, b, c] = "abc"; // ["a", "b", "c"] |
时间日期
new Date()
创建时间日期。多种参数类型:
- new Date(时间戳) ⇒ new Date(24 * 3600 * 1000)
- new Date(字符串) ⇒ new Date(‘2020-11-11”)
- new Date(年月日时分秒) ⇒ new Date(year, month, date, hours, minutes, seconds, ms)。其中:
year
必须是四位数:2013
是合法的,98
是不合法的。month
计数从0
(一月)开始,到11
(十二月)结束。date
是当月的具体某一天,如果缺失,则为默认值1
。- 如果
hours/minutes/seconds/ms
缺失,则均为默认值0
。
getMonth()
获取月份是 从 0 到 11
获取年份使用 getFullYear()
而不是 getYear()
。这才是官方的。
getDay()
是获取周几而不是获取几号,获取几号是 getDate()
设置日期组件
下列方法可以设置日期/时间组件:
[setFullYear(year, [month], [date])](https://developer.mozilla.org/zh/docs/Web/JavaScript/Reference/Global_Objects/Date/setFullYear)
[setMonth(month, [date])](https://developer.mozilla.org/zh/docs/Web/JavaScript/Reference/Global_Objects/Date/setMonth)
[setDate(date)](https://developer.mozilla.org/zh/docs/Web/JavaScript/Reference/Global_Objects/Date/setDate)
[setHours(hour, [min], [sec], [ms])](https://developer.mozilla.org/zh/docs/Web/JavaScript/Reference/Global_Objects/Date/setHours)
[setMinutes(min, [sec], [ms])](https://developer.mozilla.org/zh/docs/Web/JavaScript/Reference/Global_Objects/Date/setMinutes)
[setSeconds(sec, [ms])](https://developer.mozilla.org/zh/docs/Web/JavaScript/Reference/Global_Objects/Date/setSeconds)
[setMilliseconds(ms)](https://developer.mozilla.org/zh/docs/Web/JavaScript/Reference/Global_Objects/Date/setMilliseconds)
[setTime(milliseconds)](https://developer.mozilla.org/zh/docs/Web/JavaScript/Reference/Global_Objects/Date/setTime)
(使用自 1970-01-01 00:00:00 UTC+0 以来的毫秒数来设置整个日期)
还有就是关于 UTC 的时间,可以上MDN看看。
Date.parse(str) 方法可以从一个字符串中读取日期。
字符串的格式应该为:YYYY-MM-DDTHH:mm:ss.sssZ
,其中:
YYYY-MM-DD
—— 日期:年-月-日。- 字符
"T"
是一个分隔符。 HH:mm:ss.sss
—— 时间:小时,分钟,秒,毫秒。- 可选字符
'Z'
为+-hh:mm
格式的时区。单个字符Z
代表 UTC+0 时区。
简短形式也是可以的,比如 YYYY-MM-DD
或 YYYY-MM
,甚至可以是 YYYY
。
这个用的不是很多。
JSON
JSON.stringify
还有其他两个参数
1 | let json = JSON.stringify(value[, replacer, space]) |
- value:要编码的值。
- replacer:要编码的属性数组或映射函数
function(key, value)
。返回处理后的值 - space:用于格式化的空格数量,意思就是缩进的数量。
JOSN.parse
也有第二个参数
1 | let value = JSON.parse(str, [reviver]); |
- str:要解析的 JSON 字符串。
- reviver:可选的函数 function(key,value),该函数将为每个
(key, value)
对调用,并可以对值进行转换。
reviver 的使用
1 | let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}'; |
这样使用 reviver
1 | let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}'; |