第6章 集合引用类型
# Object
显示创建对象有 2 种方式
let person = new Object()
person.name = 'jack'
let man = {
name: 'rose',
}
2
3
4
5
6
对象访问属性也有 2 种方式
let person = {}
person.name = 'jack'
person['first name'] = 'blues'
// 只有中括号可以访问变量
let firstName = 'first name'
person[firstName] = 'brown'
2
3
4
5
6
7
# Array
更多 es6 Array 特性 es6-Array (opens new window)
# 创建数组
有 4 种方式
Array 构造函数
字面量[]
from()
接收 2 个参数,第一个参数是类数组对象或者有 length 属性即可,第二个参数是映射函数,类似数组 map 方法。
let nums = [1, 2, 3, 4]
let map = new Map().set('name', 'jack')
let set = new Set().add(1).add(2)
let mapArr = Array.from(map)
let setArr = Array.from(set)
let arr1 = Array.from(nums, (x) => 2 * x)
let arr2 = Array.from({ length: 2 }, () => Array(3).fill(2))
console.log(mapArr)
console.log(setArr)
console.log(arr1)
console.log(arr2)
2
3
4
5
6
7
8
9
10
11
12
其实还有第 3 个参数,使用较少,就不介绍了。
- of()
console.log(Array.of(1, 2, 3, 4)) // [1,2,3,4]
# 数组索引
数组是有序的集合,每个元素对应到一个索引,反映了它在数组中的顺序。
let arr = [10, 20, 30, 40]
console.log(arr.length) // 4
console.log(arr[4]) // undefined
console.log(arr[3]) // 40
2
3
4
# 检测数组
使用 Array.isArray()
# 迭代器方法
es6 方法,包括 keys()、values()和 entries()
let nums = ['a', 'b', 'c']
for (let [index, item] of nums.entries()) {
console.log(index, item)
}
// 0 a
// 1 b
// 2 c
2
3
4
5
6
7
# 复制和填充
批量复制 fill()
填充数组 copyWithin()
let zeros = [0, 0, 0, 0, 0]
zeros.fill(7, 1, 3)
console.log(zeros) // [ 0, 7, 7, 0, 0 ]
let nums = [1, 2, 3, 4, 5]
nums.copyWithin(1, 2, 4)
console.log(nums) // [ 1, 3, 4, 4, 5 ]
2
3
4
5
6
7
注意,这 2 个方法索引范围是包左不包右,如上述[1,3)和[2,4)。
# 转换
join():将数组转为字符串
let colors = ['red', 'green', 'blue']
console.log(colors.join('|')) // red|green|blue
2
# 栈和队列
栈是后进先出的数据结构,提供了 push()和 pop()实现。
队列是先进先出,提供 shift()和 unshift()
注意:这 4 个方法都会修改原数组。
# 排序方法
reserve():反向排序数组
sort():将数组元素转为字符串来比较,进行排序,接收的参数是比较函数
let values = [1, 3, 2, 5, 4]
values.sort((a, b) => b - a)
console.log(values) // [ 5, 4, 3, 2, 1 ]
2
3
注意:这 2 个方法都会修改原数组。
# 操作方法
# concat()
先创建一个数组副本,再将参数(可以是数组或元素)依次添加到末尾。默认会铺开第一层
let colors = ['red', 'green']
let colors2 = colors.concat('blue', ['yellow', 'white'])
console.log(colors2) // [ 'red', 'green', 'blue', 'yellow', 'white' ]
2
3
# slice(start,end)
截取从索引 start 到 end 的所有元素,组成新数组,end 默认是 length
let nums = [1, 2, 3, 4, 5]
console.log(nums.slice(2)) // [ 3, 4, 5 ]
console.log(nums.slice(2, 5)) // [ 3, 4 ]
console.log(nums.slice(2, 4)) // [ 3, 4, 5 ]
2
3
4
# splice(index,number,element1,element2)
它的使用方法是,在 index 位置,删除 number 个元素,然后新增 element1,element2 等等
let nums = [1, 2, 3, 4, 5]
nums.splice(1, 1)
console.log(nums) // [ 1, 3, 4, 5 ]
nums = [1, 2, 3, 4, 5]
nums.splice(1, 0, 20)
console.log(nums) // [ 1, 20, 2, 3, 4, 5 ]
nums = [1, 2, 3, 4, 5]
nums.splice(1, 1, 20, 30)
console.log(nums) // [ 1, 20, 30, 3, 4, 5 ]
2
3
4
5
6
7
8
9
10
11
# 搜索位置
# indexOf()、lastIndexOf()和 includes()
# find()和 findIndex()
# 迭代方法
# forEach()
单纯的遍历
# map()
映射数组
# filter()
筛选符合条件的元素
# every()
所有符合元素符合条件才返回 true
# some()
只要一个元素符合条件就返回 true
# 归并方法
# reduce(fn)
累加器,其中 fn 包含 4 个参数,依次是
total:每轮迭代中的归并值
item:当前项
index:当前项索引
arr:数组本身
let nums = [1, 2, 3, 4]
let sum = nums.reduce((total, item) => {
// 1 2
// 3 3
// 6 4
console.log(total, item)
return total + item
})
console.log(sum) // 10
2
3
4
5
6
7
8
9
10
# reduceRight()
反向累加器,跟 reduce 功能类似,区别在于遍历方向相反。
# 定型数组
定型数组(typed array)是 ECMAScript 新增的结构,目的是提升与 WebGL 等原生库交换二进制数据的效率。
除非是开发 WebGL 和复杂 canvas,否则基本使用不到定型数组。
相关概念
- ArrayBuffer
- DataView
# Map
Map 可以使用任何 JavaScript 数据类型作为键。
# 基本 API
创建 Map
const m = new Map()
const m1 = new Map([
['key1', 'value1'],
['key2', 'value2'],
['key3', 'value3'],
])
2
3
4
5
6
添加,查询,删除如下
m.set('name', 'jack').set('age', 18)
console.log(m.size) // 键值对数量
console.log(m.has('name')) // 查询是否存在键
console.log(m.get('name')) // 查询键对应的值
m.delete('name') // 删除指定键值对
console.log(m.has('name'))
console.log(m.has('age'))
m.clear() // 清除map实例的所有键值对
console.log(m.has('name'))
console.log(m.has('age'))
2
3
4
5
6
7
8
9
10
11
12
# 顺序与迭代
与 Object 不同,Map 实例会维护键值对的插入顺序,同时可以对其进行迭代操作。
const m = new Map()
m.set('name', 'jack').set('age', 18)
for (let [key, value] of m.entries()) {
// name jack
// age 18
console.log(key, value)
}
2
3
4
5
6
7
# 选择 Object 还是 Map
从下面 4 个方面进行对比
内存占用 | 插入性能 | 查找速度 | 删除性能 | |
---|---|---|---|---|
Map | 比 Object 多存储 50%的键值对 | 大量插入时快 | 快 | |
Object | 快 |
# WeakMap
弱映射,描述的是 JavaScript 垃圾回收程序对待若映射中键的方式。它是弱引用,不会阻止垃圾回收程序,而如果是 Map,则会强引用,垃圾回收机制无法回收。
特点:
- 键只能是 Object 或者继承自 Object 类型,否则会报错。
- 有 get,has,delete 方法
- 没有 size 属性,不可迭代
- 没有 clear 方法
const User = (() => {
const wm = new WeakMap()
class User {
constructor(id) {
this.property = Symbol('id')
this.setId(id)
}
getId() {
return wm.get(this)[this.property]
}
setId(id) {
const _this = wm.get(this) || {}
_this[this.property] = id
wm.set(this, _this)
}
}
return User
})()
const user = new User(123)
console.log(user.getId()) // 123
user.setId(456)
console.log(user.getId()) // 456
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Set
# 基本 API
const arr = [1, 2, 3]
const set = new Set(arr)
set.add(4).add(4) // 去重
console.log(set.size) // 获取元素数量
console.log(set.has(4)) // 判断元素是否存在
set.delete(3) // 删除元素
console.log(set.has(3))
console.log(set.has(4))
set.clear() // 清空全部元素
console.log(set.size)
console.log(set.has(4))
2
3
4
5
6
7
8
9
10
11
# 顺序与迭代
const arr = [1, 2, 3]
const set = new Set(arr)
for (let item of set) {
console.log(item) // 1 2 3
}
console.log([...set]) // [ 1, 2, 3 ]
2
3
4
5
6
# WeapSet
弱集合,这个弱的特性与 WeakMap 相似,不会阻止垃圾回收。
特点:
- 弱集合中的值只能是 Object 或继承自 Object 的类型。
- 有 add,has,delete 方法
- 没有 celar 方法
- 没有 size 属性,不可迭代