面试题:ES6新增了两种引用数据类型Set和Map,是为了解决哪些问题?weakSet 和 weakMap 与 Set 和 Map的区别?

前言

回答这个问题前,我们要先了解Set和Map的特点,结合它的特点去回答这个问题。

如果发现文章有错误或歧义的地方,希望各位大佬指出,避免误导更多人!!


正文

1. set

基本使用

Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。它类似于数组,但是成员的值都是唯一的,没有重复的值

  • null和undefined都可以被存储在Set 中
  • NaN之间被视为相同的值(NaN被认为是相同的,尽管 NaN !== NaN)。
  • 两个对象总是不相等的(地址不同),哪怕是空对象。

可以使用Set()创建一个新的Set对象。

const s = new Set();
// add()方法向 Set 结构加入成员
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));

for (let i of s) {
    
    
  console.log(i);
}
// 输出:2 3 5 4

Set函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。

const set = new Set([1, 2, 3, 4, 4]);
console.log([...set]); // [1, 2, 3, 4]

const set=new Set('ababbc');
console.log(set); //Set(3) { 'a', 'b', 'c' }

所以我们可以用来实现数组去重或字符串去重

// 去除数组的重复成员
[...new Set([1,2,1,3,4])]  //[ 1, 2, 3, 4 ]

//去除字符串里面的重复字符。
[...new Set('ababbc')].join('') // "abc"

属性和方法

Set.prototype.size

Set.prototype.size:返回Set实例的成员总数。

let set=new Set()
set.add({
    
    });
set.add({
    
    });
console.log(set.size);  //2

Set.prototype.add(value)

add()方法用来向一个 Set 对象的末尾添加一个指定的值。返回值是Set 对象本身。

let set=new Set()
set.add(1).add(2).add(2).add(3);
console.log(set.size); //3

Set.prototype.delete(value)

delete()方法可以从一个 Set 对象中删除指定的元素。

var mySet = new Set();
mySet.add("foo");
console.log(mySet.delete("bar")); // 返回 false,不包含 "bar" 这个元素
console.log(mySet.delete("foo")); // 返回 true,删除成功

Set.prototype.has(value)

has()方法返回一个布尔值来指示对应的值value是否存在Set对象中。

var mySet = new Set();
mySet.add("foo");
console.log(mySet.has("foo")); // 返回 true
console.log(mySet.has("bar")); // 返回 false

Set.prototype.clear()

clear() 方法用来清空一个 Set 对象中的所有元素。

var mySet = new Set();
mySet.add(1);
mySet.add(2);
console.log(mySet.size); // 2
mySet.clear()
console.log(mySet.size); // 0

Set.prototype.entries()

entries()方法返回一个新的迭代器对象。返回值一个新的包含 [value, value] 形式的数组迭代器对象,value 是给定集合中的每个元素,迭代器 对象元素的顺序即集合对象中元素插入的顺序。

var mySet = new Set();
mySet.add("foobar");
mySet.add(1);
mySet.add("baz");
var setIter = mySet.entries();
console.log(setIter.next().value); // ["foobar", "foobar"]
console.log(setIter.next().value); // [1, 1]
console.log(setIter.next().value); // ["baz", "baz"]

Set.prototype.forEach()

forEach方法会根据集合中元素的插入顺序,依次执行提供的回调函数。

var set=new Set()
set.add('hello')
set.add('world')
set.forEach((currentValue, currentKey)=>{
    
    
    console.log(currentValue,currentKey);
})
//hello hello
//world world

Set.prototype.values()

values()方法按照元素插入顺序返回一个具有 Set 对象每个元素值的全新 Iterator 对象。

var set=new Set()
set.add('hello')
set.add('world')
const iterator1 = set.values();
console.log(iterator1.next().value); //hello
console.log(iterator1.next().value); //world

扩展运算符(…)

扩展运算符(…)内部使用for…of循环,所以也可以用于 Set 结构。

let set = new Set(['red', 'green', 'blue']);
let arr = [...set]; // ['red', 'green', 'blue']

2.WeakSet

WeakSet 对象允许你将弱保持对象存储在一个集合中。

var Wset = new WeakSet([[1, 2], [3, 4]])
console.log(Wset); //WeakSet {[1, 2], [3, 4]}

WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。

  • WeakSet 的成员只能是对象,而不能是其他类型的值。
  • WeakSet 中的对象都是弱引用。如果没有其他的对WeakSet中对象的引用,那么这些对象会被当成垃圾回收掉。 这也意味着WeakSet中没有存储当前对象的列表。 正因为这样,WeakSet 是不可枚举的

WeakSet不可遍历,没有size属性,也没有clear()方法,与set相同的方法有三个

WeakSet.prototype.add(value):向 WeakSet 实例添加一个新成员。
WeakSet.prototype.delete(value):清除 WeakSet 实例的指定成员。
WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在

3.Map

Map 对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值) 都可以作为一个键或一个值。

  • Map 默认情况不包含任何键。只包含显式插入的键。一个 Object 有一个原型, 原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。
  • 一个 Map的键可以是任意值,包括函数、对象或任意基本类型。 一个Object 的键必须是一个 String 或是Symbol。
  • Map在频繁增删键值对的场景下表现更好。

基本使用

使用构造函数Map()创建 Map 对象。Map 也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构都可以当作Map构造函数的参数

let myMap = new Map();

const map = new Map([
  ['name', '张三'],
  ['title', 'Author']
]);

属性

size 是可访问属性,用于返回 一个Map 对象的成员数量。

const map = new Map();
map.set('foo', true);
map.set('bar', false);
console.log(map.size ); // 2

基本方法

Map.prototype.set(key, value)

set() 方法为 Map 对象添加或更新一个指定了键(key)和值(value)的(新)键值对,其返回Map 对象

let map = new Map()
  .set(1, 'a')
  .set(2, 'b')
  .set(3, 'c');
console.log(map.size); // 3

Map.prototype.get(key)

get()方法返回某个 Map 对象中的一个指定元素,其返回一个 Map 对象中与指定键相关联的值,如果找不到这个键则返回 undefined。

var myMap = new Map();
myMap.set("bar", "foo");

myMap.get("bar");  // 返回 "foo"
myMap.get("baz");  // 返回 undefined

Map.prototype.has(key)

has()返回一个bool值,用来表明map 中是否存在指定元素.

var myMap = new Map();
myMap.set("bar", "foo");
console.log(myMap.has("bar"));  // 返回 true
console.log( myMap.has("baz"));  // 返回 false

Map.prototype.delete(key)

delete() 方法用于移除 Map 对象中指定的元素。如果 Map 对象中存在该元素,则移除它并返回 true;否则如果该元素不存在则返回 false。

var myMap = new Map();
myMap.set("bar", "foo");

console.log(myMap.delete("bar")); // 返回 true。成功地移除元素
console.log(myMap.has("bar"));   // 返回 false。"bar" 元素将不再存在于 Map 实例中

Map.prototype.clear()

clear()方法会移除Map对象中的所有元素。

let map = new Map();
map.set('foo', true);
map.set('bar', false);

map.size // 2
map.clear()
map.size // 0

Map.prototype.entries()

entries() 方法返回一个新的包含 [key, value] 对的 Iterator 对象,返回的迭代器的迭代顺序与 Map 对象的插入顺序相同。

const map1 = new Map();

map1.set('0', 'foo');
map1.set(1, 'bar');

const iterator1 = map1.entries();

console.log(iterator1.next().value);
// expected output: ["0", "foo"]

console.log(iterator1.next().value);
// expected output: [1, "bar"]

其他遍历

  • Map.prototype.keys():返回键名的遍历器。
  • Map.prototype.values():返回键值的遍历器。
  • Map.prototype.forEach():遍历 Map 的所有成员。
  • for…of…

将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']]

4. WeakMap

WeakMap 对象是一组键/值对的集合,其中的键是弱引用的其键必须是对象,而值可以是任意的。

原生的 WeakMap 持有的是每个键对象的“弱引用”,这意味着在没有其他引用存在时垃圾回收能正确进行。 正由于这样的弱引用,WeakMap 的 key 是不可枚举的。

  • WeakMap():创建一个新的 WeakMap 对象。
  • WeakMap.prototype.delete(key):删除 WeakMap 中与 key 相关联的值。
  • WeakMap.prototype.get(key): 返回 WeakMap 中与 key 相关联的值,如果 key 不存在则返回 undefined。
  • WeakMap.prototype.has(key):返回一个布尔值,断言一个值是否已经与 WeakMap 对象中的 key 关联。
  • WeakMap.prototype.set(key, value):给 WeakMap 中的 key 设置一个 value。该方法返回一个 WeakMap 对象。

问题回答

1.为什么要新增 Set 和 Map,是为了解决哪些问题?

set的成员的值都是唯一的,没有重复元素,而数组不是。
一个 Map的键可以是任意值,包括函数、对象或任意基本类型。 但是一个Object 的键必须是一个 String 或是Symbol。Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。

2.weakSet 和 weakMap 对比 Set 和 Map

WeakSet 的成员必须是对象弱引用
WeakMap 的必须是对象且是弱引用
都不能枚举

猜你喜欢

转载自blog.csdn.net/qq_45890970/article/details/123639035