Symbol
Symbol是ES6中新增的一个基本数据类型,翻译为符号。
Symbol的作用
- Symbol生成的是一个独一无二的值。
- Symbol值是通过Symbol函数来生成的,生成后可以作为属性名。
- 在ES6中,对象的属性名可以使用字符串,也可以使用Symbol值。
- Symbol即使多次创建值,它们也是不同的:Symbol函数执行后每次创建出来的值都是独一无二的。
- 可以在创建Symbol值的时候传入一个描述description(es10)
const s1 = Symbol()
const s2 = Symbol()
console.log(s1 === s2); // false
const s3 = Symbol('xt')
console.log(s3.description); // xt
const obj = {
[s1]: 'a',
[s2]: 'b'
}
obj[s3] = 'c'
const s4 = Symbol()
Object.defineProperty(obj, s4, {
value: 'xyz',
enumerable: true,
configurable: true,
writable: true
})
console.log(obj);
// {
// [Symbol()]: 'a',
// [Symbol()]: 'b',
// [Symbol(xt)]: 'c',
// [Symbol()]: 'xyz'
// }
console.log(obj[s1]); // a 这个不能用obj.s1
// 使用symbol作为key的属性名,无法在遍历中获取到值,如果一定要获取需要使用
console.log(Object.keys(obj)); // []
const symbolKeys = Object.getOwnPropertySymbols(obj)
console.log(symbolKeys); // [ Symbol(), Symbol(), Symbol(xt), Symbol() ]
我们前面说了通过Symbol()创建的值是独一无法的,那么如何创建相同的Symbol呢?
const s1 = Symbol.for('a')
const s2 = Symbol.for('a')
console.log(s1 === s2); // true
// 可以通过Symbol.keyFor方法来获取对应的key
const key = Symbol.keyFor(s1)
console.log(key); // a
const s3 = Symbol.for(key)
console.log(s1 === s3); // true
Set
在ES6之前,我们存储数据的结构主要有两种:数组、对象。在ES6中新增了另外两种数据结构:Set、Map,以及它们的另外形式WeakSet、WeakMap。
Set是一个新增的数据结构,可以用来保存数据,类似于数组,但是和数组的区别是元素不能重复。所以Set有一个非常常用的功能就是给数组去重。
创建Set我们需要通过Set构造函数
const set1 = new Set()
set1.add(1)
set1.add(2)
set1.add(3)
console.log(set1); // Set(3) { 1, 2, 3 }
const set2 = new Set([1, ,2, 3, 1])
console.log(set1); // Set(3) { 1, 2, 3 }
console.log(set1.size); // 3
// 将set类型转数组
const newArr = [...set1]
const newArr1 = Array.from(set1)
console.log(newArr); // [ 1, 2, 3 ]
console.log(newArr1); // [ 1, 2, 3 ]
Set的常见方法
- add(value):添加某个元素,返回Set对象本身
- delete(value):从set中删除和这个值相等的元素,返回boolean类型
- has(value):判断set中是否存在某个元素,返回boolean类型
- clear():清空set中所有的元素,没有返回值
- forEach(callback, [, thisArg]):通过forEach遍历set
- 持for of遍历
WeakSet
和Set类似的另外一个数据结构称之为WeakSet,也是内部元素不能重复的数据结构
与set的区别
- WeakSet中只能存放对象类型,不能存放基本数据类型
- WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么GC可以对该对象进行回收
- WeakSet不能遍历
WeakSet常见的方法
- add(value):添加某个元素,返回WeakSet对象本身
- delete(value):从WeakSet中删除和这个值相等的元素,返回boolean类型
- has(value):判断WeakSet中是否存在某个元素,返回boolean类型
const wset = new WeakSet()
// 作用
class Person {
constructor() {
wset.add(this)
}
eating() {
if (!wset.has(this)) throw new Error('不能通过其他对象调用')
console.log(111);
}
}
const p = new Person()
p.eating()
// p.eating.call('11') // 报错
Map
Map,用于存储映射关系。
map与对象的区别:对象存储映射关系只能用字符串(ES6新增了Symbol)作为属性名(key),但是Map可以使用任意类型作为属性名(key)
const obj1 = { name: 'xt' }
const obj2 = { name: 'tx' }
const map = new Map()
map.set(obj1, 'xt')
map.set(obj2, 'tx')
console.log(map); // Map(2) { { name: 'xt' } => 'xt', { name: 'tx' } => 'tx' }
console.log(map.get(obj1)); // xt
console.log(map.get(obj2)); // tx
const map1 = new Map([[obj1, 'a'], [obj2, 'b']]) // Map(2) { { name: 'xt' } => 'a', { name: 'tx' } => 'b' }
console.log(map1);
属性
size:返回Map中元素的个数
方法
- set(key, value):在Map中添加key、value,并且返回整个Map对象
- get(key):根据key获取Map中的value
- has(key):判断是否包括某一个key,返回Boolean类型
- delete(key):根据key删除一个键值对,返回Boolean类型
- clear():清空所有的元素
- forEach(callback, [, thisArg]):通过forEach遍历Map,也可以通过for of进行遍历
WeakMap
Map类型的另外一个数据结构称之为WeakMap,也是以键值对的形式存在的
与Map的区别
- WeakMap的key只能使用对象,不接受其他的类型作为key
- WeakMap的key对对象的引用是弱引用,如果没有其他引用引用这个对象,那么GC可以回收该对象
- WeakMap也是不能遍历的
// vue3的响应式的实现就有用WeakMap
const targetMap = new WeakMap()