致自己
自从工作后很久没有看书也没有更文了,因为开发任务重并且逻辑极其复杂,每天回家后什么都不想干了,但是,每天脑海中都有一个声音在提醒我,不能就这样下去,否则终将被时代淘汰。
做技术的核心就在于学习,不断的学习,只有这样才能立于潮头而不会被拍在沙滩上,所以我只能自己鞭策自己向前赶,加油!
Map
1. Map的含义和基本用法
在出现Map之前,我们一直使用Object来存储键值对组合,但是这样有一个很大的弊端就是,key-value组合的key必须是字符串,如果不是字符串则会被强制转为字符串:
const data = {};
const element = document.getElementsByTagName('div')
data[element] = 'metadata';
data['[object HTMLDivElement]'] // "metadata"
element.toString() // "[object HTMLCollection]"
通过上面的代码我们可以看出当我们想用一个DOM节点来当做对象的key的时候,系统会先调用key的toString()方法,那么这样就会使我们在使用Object数据结构来做key-value存储时带来了一些风险,因为有时我们可能对key的toString()并不太了解。所以我们需要使用一种能够使用任何值作为key或者value的数据结构。
cosnt m = new Map()
const key = {name: 'bing'}
m.set(key, 111)
m.has(key) // true
m.get(key) // 111
m.size // 1
上面的代码展示了Map的一般用法,Map构造函数接受一个数组生成Map数据结构。
let arr = [['name', 'bing'], ['age', 23]]
let map = new Map(arr)
// 等价于
arr.forEach([key, value] => {
map.set(key, value)
})
其实,不仅仅是数组,任何成员是一个双元素对并且具有Iterator接口数据结构都能生成Map数据结构,比如使用Set
注意:
- 如果使用
set方法连续对两个相同的键赋值。那么后面的值会覆盖掉前面的值。 - 如果使用
get读取一个位置的键值,那么返回undefined。 - 如果
set的key是一个对象,那么必须是对同一个对象的引用才能被视作同一个键,即这里看得是内存地址。
2.Map 的实例属性和方法
2.1 size属性
size返回Map的成员总数
2.2 Map.prototype.set(key, value)
set方法设置键名key对应的键值为value,然后返回整个Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。
2.3 Map.prototpye.get(key)
使用get从Map中取键为key的值
2.4 Map.prototype.has(key)
判断该Map结构中是否有含有该key的键值对,该方法返回一个布尔值来表示是否存在
2.5 Map.prototype.delete(key)
delete方法用来删除某个键,如果成功就返回true失败返回false
const map = new Map([['name', 'bing'], ['age', 23]])
map.delete('name') // true
map.delete('name') // false
可以看到,如果这个键不存在与该Map结构中,如果使用删除操作也是会被判定失败的。
2.6 Map.prototype.clear()
清除Map中所有的值,该方法没有返回值。
3. Map的遍历操作
Map提供3个遍历器生辰函数和一个遍历方法:
-
Map.prototype.keys():返回键名的遍历器。 -
Map.prototype.values():返回键值的遍历器。 -
Map.prototype.entries():返回所有成员的遍历器。 -
Map.prototype.forEach():遍历 Map 的所有成员。
值得注意的是,返回遍历器的元素的顺序就是Map插入元素的顺序
let map = new Map()
map.set('name', 'bing')
map.set('age', 23)
for (let [key, value] of map.entries()) {
console.log(key, value)
}
// name bing
// age 23
for (let [key, value] of map) {
console.log(key, value)
}
// name bing
// age 23
通过上面的代码可以看出Map的Iterator接口默认就是entries方法
4. 关于Map的编程技巧
4.1
Map本身不具备数组的遍历方法,除了forEach,这时候我们可以通过扩展运算符将Map快速转成Array,然后调用数组的遍历方法,操作完之后再使用构造函数Map()将其转为Map
4.2
Map的forEach方法可以接受第二个参数来绑定this,这样我们就可以在forEach的函数作用域内来对this绑定的对象进行操作,例如:
let map = new Map()
map.set('name', 'bing')
map.set('age', 23)
let person = {}
map.forEach(function(key, value){
this[key] = value
}, person)
person // {23: "age", bing: "name"}
请注意key和value的位置,这里很容易形成误导。
值得注意的是,这里可能会有人犯一个非常小的错误,就是我们可能在平时开发中经常使用箭头函数,在这里我们如果将传入forrrEach的方法使用箭头函数定义了,那么函数将不能正常执行,因为箭头函数会绑定this为其定义时的环境。一般情况下,这里的this都会是Window。
let map = new Map()
map.set('name', 'bing')
map.set('age', 23)
let person = {}
map.forEach((value, key) => {
this[key] = value
}, person)
person // {}
window.name // "bing"
window.age // 23
4.3 Array转Map
可以通过构造函数很方便地将数组转为Map。
let arr = [['name', 'bing']]
const map = new Map(arr)
map // {"name" => "bing"}
4.4 Map转为Array
使用扩展运算符能够很方便的将Map转为Array
let map = new Map().set('name', 'bing')
let arr = [...map]
arr // ["name", "bing"]
4.5 Map和Object的相互转换
这两种数据结构之间的相互转换主要依靠遍历,然后调用赋值语句或者Map的set方法。
4.6 Map 转为 JSON
分两种情况讨论,如果Map的键名都是字符串,那么我们可以先把Map转为对象,然后再转为JSON,其次,如果Map的键有的不是字符串,那么我们可以考虑将其转为数组,然后再将其转为JSON,这样的话,我们就可以保留特殊键。
参考链接
作者:阮一峰
连接:http://es6.ruanyifeng.com/#docs/set-map








网友评论