乐趣区

关于javascript:javascript高级程序设计学习笔记-64Map

关注前端小讴,浏览更多原创技术文章

Map

  • Map 是 ECMAScript6 的新增个性,是一种新的 汇合类型,其大多数个性都能够通过 Object 类型实现

相干代码 →

根本 API

  • 应用 new 关键字Map 构造函数 能够创立一个空映射
const m = new Map()
console.log(m) // Map(0) {}
  • 能够给 Map 构造函数 传入一个可迭代对象 ,须要蕴含 键 / 值对数组
// 嵌套数组初始化映射
const m1 = new Map([['key1', 'val1'],
  ['key2', 'val2'],
  ['key3', 'val3'],
])
console.log(m1) // Map(3) {'key1' => 'val1', 'key2' => 'val2', 'key3' => 'val3'}

// 自定义迭代器初始化映射
const m2 = new Map({[Symbol.iterator]: function* () {yield ['key1', 'val1']
    yield ['key2', 'val2']
    yield ['key3', 'val3']
  },
})
console.log(m2) // Map(3) {'key1' => 'val1', 'key2' => 'val2', 'key3' => 'val3'}
  • 初始化后,能够应用 set() 增加键 / 值对,应用 get()has()进行查问,通过 size 属性获取映射中的键值对数量,应用 delete()clear()删除值
const m3 = new Map()
console.log(m3.size) // 0

m.set('firstName', 'Matt').set('lastName', 'Frisbie')
console.log(m.has('firstName')) // true
console.log(m.get('firstName')) // 'Matt'
console.log(m.size) // 2

m.delete('firstName') // 删除这个键值对
console.log(m.has('firstName')) // false
console.log(m.get('firstName')) // undefined
console.log(m.has('lastName')) // true
console.log(m.size) // 1

m.clear() // 革除所有键值对
console.log(m.has('firstName')) // false
console.log(m.has('lastName')) // false
console.log(m.size) // 0
  • set()办法返回映射实例,因而能够把多个操作连缀起来,从初始化到增加键 / 值对:
const m4 = new Map().set('key1', 'val1')
console.log(m4) // Map(1) {'key1' => 'val1'}
  • object 只能应用 数值、字符串或符号 作为键不同,Map能够应用 任何 JS 数据类型 作为建
const m5 = new Map()

const functionKey = function () {}
const symbolKey = Symbol()
const objectKey = new Object()

m5.set(functionKey, 'functionValue')
  .set(symbolKey, 'symbolValue')
  .set(objectKey, 'objectValue')

console.log(m5.get(functionKey)) // 'functionValue'
console.log(m5.get(symbolKey)) // 'symbolValue'
console.log(m5.get(objectKey)) // 'objectValue'
  • Object 一样,若键或值是对象或其余“汇合类型”,当键或值的内容或属性被批改时,映射也受到影响
const m6 = new Map()

const objKey = {},
  objValue = {},
  arrKey = [],
  arrValue = []

m6.set(objKey, objKey)
m6.set(arrKey, arrValue)
console.log(m6) // Map(2) {{} => {}, [] => []}

objKey.foo = 'foo'
objValue.bar = 'bar'
arrKey.push('foo')
arrValue.push('bar')
console.log(m6) // Map(2) {{ foo: 'foo'} => {foo: 'foo'}, ['foo'] => ['bar'] }
console.log(m6.get(objKey)) // {foo: 'foo'}
console.log(m6.get(arrKey)) // ['bar']

程序与迭代

  • Object 不同,Map 保护键值对的插入程序 (Object 是无序的),能够 依据插入程序 执行 迭代操作

    • 映射实例能够提供一个迭代器 Iterator,能以插入程序生成[key,value] 模式的数组
    • 能够通过 entries() 办法或 Symbol.iterator 属性获得这个迭代器
const m7 = new Map([['key1', 'val1'],
  ['key2', 'val2'],
  ['key3', 'val3'],
])
console.log(m7.entries === m7[Symbol.iterator]) // true

for (let pair of m7.entries()) {console.log(pair)
  /* 
    ['key1', 'val1']
    ['key2', 'val2']
    ['key3', 'val3']
  */
}
for (let pair of m7[Symbol.iterator]()) {console.log(pair)
  /* 
    ['key1', 'val1']
    ['key2', 'val2']
    ['key3', 'val3']
  */
}
  • 能够间接对映射实例应用 扩大操作,把映射转换成数组
console.log([...m7]) // [[ 'key1', 'val1'], ['key2', 'val2'], ['key3', 'val3'] ]
console.log(...m7) // ['key1', 'val1'] ['key2', 'val2'] ['key3', 'val3']
  • 如果不应用迭代器,可调用 forEach(callBack,opt_thisArg) 办法并传入回调,顺次迭代每个键值对

    • 回调的第二个可选参数用于重写回调外部 this 的值
m7.forEach((val, key) => {console.log(`${key}->${val}`)
  /* 
    key1->val1
    key2->val2
    key3->val3
  */
})
  • Array 的迭代器办法,Mapkeys()values()别离返回 以插入程序 生成的键和值的迭代器
for (let key of m7.keys()) {console.log(key)
  /* 
    key1
    key2
    key3
  */
}
for (let value of m7.values()) {console.log(value)
  /* 
    val1
    val2
    val3
  */
}
  • 迭代器遍历时,键和值均可被批改,不同类型的键或值批改会对映射造成不同影响:

    • 批改 原始值 的键或值,或重写 援用值 的键或值,映射外部的援用无奈批改,映射不受影响
    • 批改 援用值 的键或值的属性,映射外部的援用未扭转,映射不受影响
/* 字符串原始值作为键或值 */
const m8 = new Map([['key1', 'val1']])

for (let key of m8.keys()) {
  key = 'newKey' // 批改键
  console.log(key) // 'newKey'
  console.log(m8.get('key1')) // 'val1',映射外部的援用无奈批改
  console.log(m8.get('newKey')) // undefined
  console.log(m8.get(key)) // undefined
}
console.log(m8) // Map(1) {'key1' => 'val1'},映射不受影响

/* 援用值作为键或值 */
const keyObj = {id: 1}
const m9 = new Map([[keyObj, 'val2']])

for (let key of m9.keys()) {
  key.id = 2 // 批改键的属性
  console.log(key) // {id: 2}
  console.log(m9.get(key)) // val2,映射外部的援用未扭转,对象在映射外部依然援用雷同的值
}
console.log(m9) // Map(1) {{ id: 2} => 'val2' },映射受影响

for (let key of m9.keys()) {key = { id: 3} // 重写键
  console.log(key) // {id: 3}
  console.log(m9.get(key)) // undefined,映射外部的援用无奈批改
}
console.log(m9) // Map(1) {{ id: 2} => 'val2' },映射不受影响

抉择 Object 还是 Map

  • 固定大小的内存,Map 约比 Object 多存储 50% 的键值对
  • 波及大量插入操作,Map 性能更佳
  • 波及大量查找操作,Object 更适宜
  • 波及大量删除操作,毫无疑问抉择 Map

总结 & 问点

有序
Object 数值、字符串、符号
Map 任何 JS 数据类型
  • Map 属于什么类型?如何创立 Map 类型?初始化后能够对其进行哪些操作?
  • Map 能够应用哪些数据类型作为键?若键或值是对象,当其内容或属性被批改时,映射受到影响么?
  • Map 和 Object 有哪些区别?
  • 如何将 Map 转换为数组?如何获取 Map 的每一个键值对?独自的键或值呢?
  • 能够在 Map 遍历时批改外部的键或值么?批改后会对 Map 产生影响么?
退出移动版