Мало знаний, большой вызов! Эта статья участвует в "Необходимые знания для программистов«Творческая деятельность.
Как мы все знаем,Map
используется для хранения пар ключ-значение, а объекты в JavaScript также состоят из пар ключ-значение, тоMap
В чем смысл существования?
Не принимайте объекты за карту
1. Неопределенные свойства могут быть доступны через цепочку прототипов.
Предполагая существующий сценарий, для разработки веб-сайта вам необходимо предоставить три языка: японский, китайский и корейский.Мы можем определить словарь для управления им.
const dictionary = {
'ja': {
'Ninjas for hire': '忍者を雇う',
},
'zh': {
'Ninjas for hire': '忍者出租',
},
'ko': {
'Ninjas for hire': '고용 닌자',
}
}
console.log(dictionary.ja['Ninjas for hire']) // 忍者を雇う
console.log(dictionary.zh['Ninjas for hire']) // 忍者出租
console.log(dictionary.ko['Ninjas for hire']) // 고용 닌자
Таким образом мы управляем словарями разных языков. Однако проблема возникает, когда мы пытаемся получить доступ к свойству controctor.
console.log(dictionary.ko['constructor']) // ƒ Object() { [native code] }
Для несуществующих свойств мы ожидаем получитьundefined
, Результат осуществляется через цепочку прототипа до неопределенного свойства, объект прототипаconstructor
свойство, указывающее на конструктор.
Одним из решений здесь является установка прототипа наnull
Object.setPrototypeOf(dictionary.ko, null)
console.log(dictionary.ko['constructor']) // undefined
key
Сопоставленный HTML-узел. Пишем следующий код:
/* html部分
<div id="firstElement"></div>
<div id="secondElement"></div>
*/
const firstElement = document.getElementById('firstElement')
const secondElement = document.getElementById('secondElement')
const map = {}
map[firstElement] = {
data: 'firstElement'
}
map[secondElement] = {
data: 'secondElement'
}
console.log(map[firstElement].data) // secondElement
console.log(map[secondElement].data) // secondElement
Данные первого элемента перезаписываются, причина в том, что в объектеkey
Может быть только строковым типом, когда мы не используем строковый тип, он будет вызываться неявноtoString()
функция для преобразования. Таким образом, оба элемента html преобразуются в строки.[object HTMLDivElement]
.
Объектные ключи также могут бытьSymbol
, но вfor..in
траверс иObject.keys()
и сJSON.stringify()
При сериализации он будет игнорироваться какSymbol
ключ.
использовать карту
1. Сопоставьте общие операции
Карта может использовать любой тип данных JavaScript в качестве ключа
function People(name) {
this.name = name
}
const zhangsan = new People('zhangsan')
const xiaoming = new People('xiaoming')
const lihua = new People('lihua')
// 创建 Map
const map = new Map()
// 创建 Map 并进行初始化 将二维键值对数组转换成一个Map对象
const map1 = new Map([
['key1', 'val1'],
['key2', 'val2'],
])
// 将 Map 转为二维数组
console.log(Array.from(map1)) // [ [ 'key1', 'val1' ], [ 'key2', 'val2' ] ]
// 设置键值映射关系
map.set(zhangsan, { region: 'HB' })
map.set(xiaoming, { region: 'HN' })
// 根据 key 获取对应值
console.log(map.get(zhangsan)) // { region: 'HB' }
console.log(map.get(xiaoming)) // { region: 'HN' }
// 获取不存在的 key 得到 undefined
console.log(map.get(lihua)) // undefined
// 通过 has 函数判断指定 key 是否存在
console.log(map.has(lihua)) // false
console.log(map.has(xiaoming)) // true
// map存储映射个数
console.log(map.size) // 2
// delete 删除 key
map.delete(xiaoming)
console.log(map.has(xiaoming)) // false
console.log(map.size) // 1
// clear 清空 map
map.clear()
console.log(map.size) // 0
2. Перемещайтесь по карте
Карта может гарантировать, что порядок обхода соответствует порядку вставки
const zhangsan = { name: 'zhangsan' }
const xiaoming = { name: 'xiaoming' }
const map = new Map()
map.set(zhangsan, { region: 'HB' })
map.set(xiaoming, { region: 'HN' })
// 每个键值对返回的是 [key, value] 的数组
for (let item of map) { // = for (let item of map.entries()) {
console.log(item)
// [ { name: 'zhangsan' }, { region: 'HB' } ]
// [ { name: 'xiaoming' }, { region: 'HN' } ]
}
// 遍历 key
for (let key of map.keys()) {
console.log(key)
// { name: 'zhangsan' }
// { name: 'xiaoming' }
}
// 遍历 value
for (let key of map.values()) {
console.log(key)
// { region: 'HB' }
// { region: 'HN' }
}
// 使用 forEach() 方法迭代 Map
map.forEach(function(value, key) {
console.log(key, value)
// { name: 'zhangsan' } { region: 'HB' }
// { name: 'xiaoming' } { region: 'HN' }
})
3. Определите, что ключи равны в карте
Карта внутри использует операцию сравнения SameValueZero.
О SameValue и SameValueZero
SameValue (Object.is()
) И строго равен (===
) В сравнении сNaN
а также+0
,-0
Различное лечение
Object.is(NaN, NaN) // true
Object.is(0, -0) // false
0
а также-0
Равенство.
map.set(NaN, 0)
map.set(0, 0)
console.log(map.has(NaN)) // true
console.log(map.has(-0)) // true
4. Скопируйте или объедините карту
-
Карты можно копировать как массивы
let original = new Map([ [1, {}] ]) let clone = new Map(original) // 克隆 Map console.log(clone.get(1)); // {} console.log(original === clone) // false console.log(original.get(1) === clone.get(1)) // true
-
Объединение нескольких карт
let first = new Map([ [1, 'one'], [2, 'two'], [3, 'three'], ]); let second = new Map([ [1, 'uno'], [2, 'dos'] ]); // 合并两个 Map 对象时,如果有重复的键值,则后面的会覆盖前面的。 // 展开运算符本质上是将 Map 对象转换成数组。 let merged = new Map([...first, ...second]); console.log(merged.get(1)); // uno console.log(merged.get(2)); // dos console.log(merged.get(3)); // three
5. Сериализация карты
благодарный @Сердце рыбынапоминание.
Map
не может быть сериализован, если вы попытаетесь использоватьJSON.stringify
получатьMap
изJSON
, вы получите только"{}"
.
из-заMap
Ключи могут быть любого типа данных, в то время какJSON
В качестве ключей разрешены только строки, поэтому, как правило, невозможноMap
Перевести вJSON
.
Map
:
// 初始化 Map(1) {"key1" => "val1"}
const originMap = new Map([['key1', 'val1']])
// 序列化 "[[\"key1\",\"val1\"]]"
const mapStr = JSON.stringify(Array.from(originMap.entries()))
// 反序列化 Map(1) {"key1" => "val1"}
const cloneMap = new Map(JSON.parse(mapStr))
Карта объектов и разница в производительности
- использование памяти
Map
Object
Мультимагазин50%
пара ключ/значение.
- Производительность вставки
Map
Немного быстрее, рекомендуется, если задействовано много операцийMap
.
- Найти скорость
Разница в производительности минимальна, но если включить только несколько пар ключ/значение, тоObject
Иногда быстрее.Object
Браузеры оптимизируют при использовании в качестве массива. Если задействовано большое количество поисковых запросов, выберитеObject
было бы лучше.
- удалить производительность
Если код предполагает большое количество операций удаления, рекомендуется выбратьMap
.
использованная литература
- Читы JavaScript Ninja (второе издание)
- Расширенное программирование с помощью JavaScript (четвертое издание)
- Map - MDN