JavaScript进阶讲解十二—>es6~es12(二)

90 阅读4分钟

Symbol

Symbol是ES6中新增的一个基本数据类型,翻译为符号。

Symbol的作用

  1. Symbol生成的是一个独一无二的值。
  2. Symbol值是通过Symbol函数来生成的,生成后可以作为属性名
  3. 在ES6中,对象的属性名可以使用字符串,也可以使用Symbol值。
  4. Symbol即使多次创建值,它们也是不同的:Symbol函数执行后每次创建出来的值都是独一无二的。
  5. 可以在创建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的常见方法

  1. add(value):添加某个元素,返回Set对象本身
  2. delete(value):从set中删除和这个值相等的元素,返回boolean类型
  3. has(value):判断set中是否存在某个元素,返回boolean类型
  4. clear():清空set中所有的元素,没有返回值
  5. forEach(callback, [, thisArg]):通过forEach遍历set
  6. 持for of遍历

WeakSet

和Set类似的另外一个数据结构称之为WeakSet,也是内部元素不能重复的数据结构

与set的区别

  1. WeakSet中只能存放对象类型,不能存放基本数据类型
  2. WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么GC可以对该对象进行回收
  3. WeakSet不能遍历

WeakSet常见的方法

  1. add(value):添加某个元素,返回WeakSet对象本身
  2. delete(value):从WeakSet中删除和这个值相等的元素,返回boolean类型
  3. 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中元素的个数

方法

  1. set(key, value):在Map中添加key、value,并且返回整个Map对象
  2. get(key):根据key获取Map中的value
  3. has(key):判断是否包括某一个key,返回Boolean类型
  4. delete(key):根据key删除一个键值对,返回Boolean类型
  5. clear():清空所有的元素
  6. forEach(callback, [, thisArg]):通过forEach遍历Map,也可以通过for of进行遍历

WeakMap

Map类型的另外一个数据结构称之为WeakMap,也是以键值对的形式存在的

与Map的区别

  1. WeakMap的key只能使用对象,不接受其他的类型作为key
  2. WeakMap的key对对象的引用是弱引用,如果没有其他引用引用这个对象,那么GC可以回收该对象
  3. WeakMap也是不能遍历的
// vue3的响应式的实现就有用WeakMap
const targetMap = new WeakMap()