Symbol

本来有六种(Number、String、Object、Undefined、Null、Boolean)
一种新的原始数据类型(就是有七种了)

Symbol可以通过其英文含义标志、象征来理解,标志、象征是独一无二的。所以Symbol的第一个特征是,两个Symbol对象之间永远是不等的。Symbol可以认为是一种不会相等的字符串

定义Symbol输出
这里要注意,Symbol和Number、String、Object不一样,他是没有包装类型(Boolean,Number,String包装类型的作用就是可以使用方法,所以他的生命周期就是调用方法(比如说类型转换啥的)的那一瞬间。)的,加new是会报错的

let s1 = Symbol()
let s2 = Symbol('a111')

分别会输出Symbol()和Symbol(a111)(字符串注意要加’’)

es6数据类型有哪些_es6数据类型有哪些


如果参数是个对象,就会先把对象进行obj.toString()然后再传进去。

Symbol.for()
使用Symbol.for()定义的与之间定义的不同,使用Symbol.for()定义是全局的**(不管当前环境如何)**,如果再定义一个一样的,就会先找之前有没有一样的,如果有就会直接拿过来用

let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
s1 === s2 结果是true,因为s2就是把s1的那个直接拿来用了。

Symbol.keyFor()
会把全局登记的Symbol(就是用Symbol.for()定义的)括号中的内容输出出来。
下例中的sk的value是aaa。

let s = Symbol.for('aaa');
let sk = Symbol.keyFor(s);

Symbol的使用场景
1.可以当key,比如两个人名字相同,如果用名字当key后面的就会把前面的覆盖掉,这个时候用Symbol(名字)就没事了。

下面只会输出22的Leon

const name1 = 'Leon';
const name2 = 'Leon';
const Table = {
   [name1]:{age:18},
   [name2]:{age:22}
}

用Symbol两个就都出来了

const name1 = Symbol('Leon');
const name2 = Symbol('Leon');
const Table = {
   [name1]:{age:18},
   [name2]:{age:22}
}

2.保护属性
这里再例举遍历对象属性的方法for in、for of Object.keys、for of Object.getOwnPropertySymbols()(和Object.getOwnPropertyNames()相反)。前两种只能遍历普通属性,第三种只能遍历Symbol属性。
for of Reflect.ownKeys()两种都可以遍历。

3.可以消除魔术字符串
魔术字符串就是重复出现的字符串。
什么意思呢?
打个比方两个属性,如果我们并不在意里面的内容,我们之间把内容换成Symbol()就行了。

let a = {
qq:'qwertyu',
ww:'asdfghj'
}

改为

let a = {
qq:Symbol(),
ww:Symbol()
}

Set

一种新的数据结构,里面的数值都是唯一的(哈希表?和哈希表又不一样,Set也有key也有value但是key和value一样,像是一种特殊的数组)。
方法:
添加用**add()方法
删除用
delete()**方法
括号中的参数都是内容
**clear()**方法清空
**has()**方法判断有没有该元素
s.size注意用的是size不是length
数组能用的遍历Set也能用

Set的应用场景
1.去重
获得的会是一个去重之后的结果。

let arr = [1,2,3,3,4,5];
let s = new Set(arr);

可以这么快去重,那么力扣上刷题不是就特别投机了吗?
其实单单这样肯定是过不了的,因为Set毕竟只是个伪数组。
得将其变成一个真正的数组,可以用之前介绍过的Array.from方法,也可以用[…set]。

2.合并去重

let arr1 = [1,2,3,4]
let arr2 = [2,3,4,5,6]
let s = new Set([...arr1,...arr2])

3.求交集
可以通过Set中的has方法来获得交集。
这里需要再次强调的是,只要返回一个true,那么filter就会将该元素放入新的数组中(在之前的数组遍历中提过)

let arr1 = [1,2,3,6,3,4,5,5];
let arr2 = [2,3,4,5];
let s1 = new Set(arr1);
let s2 = new Set(arr2);
let result = new Set(arr1.filter(item => s2.has(item)))

console.log(result);

4.求差集
很简单,在交集的前提上取反就好了,然后将两个结果合并。

WeakSet
特殊的Set内部只能存放对象
因为存放内容是对象,所以就会有一个问题,delete()方法的参数是一个对象,前面提到过对象栈和堆的问题。也就是说如果像下面代码这样,删除是不会成功的。

let ws = new WeakSet();
ws.add({name:a,age:10});
ws.delete({name:a,age:10});

要这样处理才行。

let ws = new WeakSet();
const obj = {name:a,age:10}; 
ws.add(obj);
ws.delete(obj);

同理,用has()方法也是。
弱引用
还有一点要注意的是WeakSet是不能遍历的。

Map

之前在力扣上刷题,就觉得Map和C#里的Dictionary很像,就是一种哈希表,是一种键值对的形式。
Map添加内容的方法set(),获取用的是get(),删除用的是delete(),也有has()和size属性(对于对象内容的操作,也要注意上文WeakSet所提到的内容)。

map.set(key,value);

初始化时添加内容,要用[]数组形式每个数组会是他的成员。
1.注意外面还要加个[]
2.内部键值对中,value后的索引再写内容不会被显示。

let newM = new Map([[key,value],['a',111]]);

map.set(key,value)时,如果key已存在,会将原来存在的键值对中的value更改。
map的遍历
有三种可选

let key of map.keys
let value of map.values
let [key,value] of map.entries()

和前面相对应的,也有个WeakMap,定义也很像,WeakMap的key只能是引用类型。其他和WeakSet一样,也不支持遍历,也是弱引用。