前言
今天开始和大家一起系统的学习ES6+,每天3分钟,用一把斗地主的时间,重学ES6+,今天介绍的是新增的数据结构Symbol Map WeakMap Set WeakSet
Symbol
Symbol的基本使用
- Symbol是什么呢?Symbol是ES6中新增的一个基本数据类型,翻译为符号。
- 那么为什么需要Symbol呢?
- 在ES6之前,对象的属性名都是字符串形式,那么很容易造成属性名的冲突;
- 比如原来有一个对象,我们希望在其中添加一个新的属性和值,但是我们在不确定它原来内部有什么内容的情况下, 很容易造成冲突,从而覆盖掉它内部的某个属性;
- 比如我们在写apply、call、bind实现时,我们有给其中添加一个fn属性,那么如果它内部原来已经有了fn属性了呢?
- 比如开发中我们使用混入,那么混入中出现了同名的属性,必然有一个会被覆盖掉;
- Symbol就是为了解决上面的问题,用来生成一个独一无二的值。
- Symbol值是通过Symbol函数来生成的,生成后可以作为属性名;
- 也就是在ES6中,对象的属性名可以使用字符串,也可以使用Symbol值;
- Symbol即使多次创建值,它们也是不同的:Symbol函数执行后每次创建出来的值都是独一无二的;
- 我们也可以在创建Symbol值的时候传入一个描述description:这个是ES2019(ES10)新增的特性;
代码演示
// 1.ES6之前, 对象的属性名(key) var obj = { name: "why", friend: { name: "kobe" }, age: 18 } // obj['newName'] = "james" // console.log(obj) // 2.ES6中Symbol的基本使用 const s1 = Symbol() const s2 = Symbol() console.log(s1 === s2) // false // ES2019(ES10)中, Symbol还有一个描述(description) const s3 = Symbol("aaa") console.log(s3.description) // aaa
Symbol作为属性名
我们通常会使用Symbol在对象中表示唯一的属性名
注意: 不能通过.语法获取
使用Symbol作为key的属性名,在遍历/Object.keys等中是获取不到这些Symbol值
需要Object.getOwnPropertySymbols来获取所有Symbol的key
代码演示
// 3.Symbol值作为key // 3.1.在定义对象字面量时使用 const obj = { [s1]: "abc", [s2]: "cba" } // 3.2.新增属性 obj[s3] = "nba" // 3.3.Object.defineProperty方式 const s4 = Symbol() Object.defineProperty(obj, s4, { enumerable: true, configurable: true, writable: true, value: "mba" }) console.log(obj[s1], obj[s2], obj[s3], obj[s4]) // 注意: 不能通过.语法获取 // console.log(obj.s1) // 4.使用Symbol作为key的属性名,在遍历/Object.keys等中是获取不到这些Symbol值 // 需要Object.getOwnPropertySymbols来获取所有Symbol的key console.log(Object.keys(obj)) console.log(Object.getOwnPropertyNames(obj)) console.log(Object.getOwnPropertySymbols(obj)) const sKeys = Object.getOwnPropertySymbols(obj) for (const sKey of sKeys) { console.log(obj[sKey]) }
相同值的Symbol
- 前面我们讲Symbol的目的是为了创建一个独一无二的值,那么如果我们现在就是想创建相同的Symbol应该怎么 来做呢?
- 我们可以使用Symbol.for方法来做到这一点;
- 并且我们可以通过Symbol.keyFor方法来获取对应的key;
代码演示
const sa = Symbol.for("aaa") const sb = Symbol.for("aaa") console.log(sa === sb) // true const key = Symbol.keyFor(sa) console.log(key) // aaa const sc = Symbol.for(key) console.log(sa === sc) // true
Set
Set的基本使用
- 在ES6之前,我们存储数据的结构主要有两种:数组、对象。
- 在ES6中新增了另外两种数据结构:Set、Map,以及它们的另外形式WeakSet、WeakMap。
- Set是一个新增的数据结构,可以用来保存数据,类似于数组,但是和数组的区别是元素不能重复。
- 创建Set我们需要通过Set构造函数(暂时没有字面量创建的方式):
- 我们可以发现Set中存放的元素是不会重复的,那么Set有一个非常常用的功能就是给数组去重。
代码演示
// 1.创建Set结构 const set = new Set() set.add(10) set.add(20) set.add(40) set.add(333) set.add(10) console.log(set) //// 10, 20, 40, 333 // 3.对数组去重(去除重复的元素) const arr = [33, 10, 26, 30, 33, 26] const newArr = [] for (const item of arr) { if (newArr.indexOf(item) !== -1) { newArr.push(item) } } const arrSet = new Set(arr) const newArr = Array.from(arrSet) const newArr = [...arrSet] console.log(newArr)
Set的常见方法
- Set常见的属性:
- size:返回Set中元素的个数;
- Set常用的方法:
- add(value):添加某个元素,返回Set对象本身;
- delete(value):从set中删除和这个值相等的元素,返回boolean类型;
- has(value):判断set中是否存在某个元素,返回boolean类型;
- clear():清空set中所有的元素,没有返回值;
- forEach(callback, [, thisArg]):通过forEach遍历set;
- 另外Set是支持for of的遍历的。
代码演示
const arrSet = new Set() // size属性 console.log(arrSet.size) // Set的方法 // add arrSet.add(100) console.log(arrSet) // delete arrSet.delete(33) console.log(arrSet) // has console.log(arrSet.has(100)) // clear arrSet.clear() console.log(arrSet) // 6.对Set进行遍历 arrSet.forEach(item => { console.log(item) }) for (const item of arrSet) { console.log(item) }