ES6 之 Set和Map

948 阅读3分钟

一、Set

1.基础用法

一种新的数据结构,类似于数组,但是成员的值都是唯一的,没有重复的值。

let s1 = new Set();
s1.add(9);
let arr = [1, 2, 3, 4, 4, '4', NaN, NaN, {}, {}];
let s2 = new Set(arr);
console.log(s1);  // Set { 9 }
console.log(s2);  // Set { 1, 2, 3, 4, '4', NaN, {}, {} }
console.log([...s2])  // [ 1, 2, 3, 4, '4', NaN, {}, {} ]
console.log(Array.from(s2))  // [ 1, 2, 3, 4, '4', NaN, {}, {} ]
  • Set的参数可以为空、或者一个数组(或者具有 iterable 接口的其他数据结构)。
  • Set 内部判断两个值是否不同,类似于精确相等运算符(===),主要的区别是 NaN 视为相等。
  • 扩展运算符(...)或者Array.from 结合Set可以实现数值去重。

2.Set实例的属性和方法

let s = new Set();
//add方法 添加成员
s.add(1).add(2).add(2).add(3);
//size属性 成员数量
console.log(s.size);  // 3
//delete方法 删除成员
s.delete(1);
//has方法 检测是否为Set的成员
console.log(s.has(1)); // false
//clear方法 清空所有成员
s.clear();
console.log(s.size); // 0

3.Set实例的遍历方法

let s = new Set(['age', 'name', 'sex']);
for(let i of s.keys()) {
  console.log(i);
}
// age
// name
// sex
for(let i of s.values()) {
  console.log(i);
}
// age
// name
// sex
for(let i of s.entries()) {
  console.log(i);
}
// [ 'age', 'age' ]
// [ 'name', 'name' ]
// [ 'sex', 'sex' ]

//values方法可以省略不写
//Set的key和value又是一致的
//所以可以用简写方式代替
for(let i of s) {
  console.log(i);
}
// age
// name
// sex

for...of 是ES6新增的一种遍历方法,用来遍历带有Iterator接口的数据结构

//forEach循环和数组表现一致
s.forEach((key, value, item) => console.log(key, value, item));
// age age Set { 'age', 'name', 'sex' }
// name name Set { 'age', 'name', 'sex' }
// sex sex Set { 'age', 'name', 'sex' }

二、Map

1.基础用法

为了解决对象(Object)中的键只能是字符串的问题。
Map 也是一种键值对的集合,其中”键“的范围可以是任何类型的值

let set = new Set([
  ['name', 'nan'],
  ['age', 18]
])
const m1 = new Map(set);
console.log(set);  //Set { [ 'name', 'nan' ], [ 'age', 18 ] }
console.log(m1);  //Map { 'name' => 'nan', 'age' => 18 }

const m2 = new Map();
m2.set(Symbol('para1'), 'para1');
m2.set(0, 'para2');
m2.set(-0, 'para3');
m2.set('0', 'para4');
m2.set({}, 'para5');
m2.set({}, 'para6');
m2.set([], 'para7');
m2.set([], 'para8');
m2.set(true, 'para9');
m2.set(new Set(), 'para10');
m2.set(() => {}, 'para11');
m2.set(() => {}, 'para12');
m2.set(undefined, 'para13');
m2.set(null, 'para14');
m2.set(NaN, 'para15');
m2.set(NaN, 'para16');
console.log(m2);
/*
  Map {
    Symbol(para1) => 'para1',
    0 => 'para3',
    '0' => 'para4',
    {} => 'para5',
    {} => 'para6',
    [] => 'para7',
    [] => 'para8',
    true => 'para9',
    Set {} => 'para10',
    [Function] => 'para11',
    [Function] => 'para12',
    undefined => 'para13',
    null => 'para14',
    NaN => 'para16' 
  }
*/
  • Map的参数可以为空,或者一个二维数组(或者具有 Iterator 接口的二维数组的数据结构)
  • Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。

2.Map实例的属性和方法

const m = new Map();
//.set(key, value) 添加成员
m.set('name', 'nan').set('age', 18).set(symbol = Symbol('test'), 'test');
//.size 成员数量
console.log(m.size)  //2
//.get(key) 读取成员 找不到返回undefined
console.log(m.get(symbol))  //test
//.has(key) 返回一个布尔值
console.log(m.has('age'))  //true
//.delete(key) 删除某个键 返回布尔值
console.log(m.delete('age'))  //true
console.log(m.has('age')) //false
//.clear() 清空Map
m.clear()
console.log(m.size) //0

3.Map实例的遍历方法

const map = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);

console.log([...map.keys()])
// [1, 2, 3]
console.log([...map.values()])
// ['one', 'two', 'three']
console.log([...map.entries()])
// [[1,'one'], [2, 'two'], [3, 'three']]
//等同于map.entries()
for (let [key, value] of map) {
  console.log(key, value)
}
// 1 'one'
// 2 'two'
// 3 'three'

map.forEach(function(value, key, map) {
  console.log("Key: %s, Value: %s", key, value);
});
// Key: 1, Value: one
// Key: 2, Value: two
// Key: 3, Value: three

三、WeakSet & WeakMap

1.WeakSet与Set的区别

1.WeakSet的成员只能是对象
let weakSet = new WeakSet();
weakSet.add('name');  //TypeError: Invalid value used in weak set
2.WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用

由于上面这个特点,WeakSet 的成员是不适合引用的,因为它会随时消失。
WeakSet 没有size属性,也不可遍历

2.WeakMap与Map的区别

1.WeakMap只接受对象作为键名(null除外)
const weakMap = new WeakMap();
weakMap.set(1, 2)
// TypeError: Invalid value used as weak map key
weakMap.set(Symbol(), 2)
// TypeError: Invalid value used as weak map key
weakMap.set(null, 2)
// TypeError: Invalid value used as weak map key
2.WeakMap的键名所指向的对象,不计入垃圾回收机制。

WeakMap结构有助于防止内存泄漏
没有size属性,无法遍历

参考文献
es6.ruanyifeng.com/#docs/set-m…