ES6标准入门 学习笔记 (04)

134 阅读4分钟

引入

系统学习ES6各种特性,了解背后的原理。

本章记录SymbolSet还有Map三种数据类型的使用

笔记

1. Symbol

1.1 概述

Symbol类型是ES6引入的新的数据类型,表示独一无二的值

通过Symbol()创建,是一种值类型(不是对象,类似于字符串)

可以传递参数作为Symbol值的描述(非字符串会转为字符串)

注意描述仅仅是描述,相同的描述不代表Symbol值相等

此外Symbol值不能和其他类型值进行运算,否则会报错。但可以显示转为字符串、布尔值

let s = Symbol();
typeof s; //'symbol'
let s2 = Symbol('描述内容'); //可以传递参数作为Symbol的描述(非字符串会转为字符串)

1.2 作为属性名

因为每一个Symbol值都是不等的,所以可以作为标识符用于对象的属性名,保证不会出现同名属性

\\ 方式1
let s = Symbol();
let a = {
    [s]: 'Hello'
};
\\方式2
let a = {};
a[s] = 'Hello';
\\方式3
let a = {};
Object.defineProperty(a, s, {value:'Hello'});

还有一大常用方式就是作为常量(枚举值)

log.levels = {
    DEBUG: Symbol('debug'),
    INFO: Symbol('info'),
    WARN: Symbol('warn')
}
mylog(log.levels.DEBUG, 'foobar');

也能在switch语句中使用,好处有:

  1. 不可能与其他任何值重复,保证switch语句正常执行。
  2. 避免某个数值或字符串在代码中多次出现,高度耦合不利于将来的维护修改

1.3 属性名的遍历

Symbol作为属性名,不会出现在for in, for of循环中,也不会被Object.keys()等返回

但其并非私有,可以通过Object.getOwnPropertySybols(obj)得到obj的所有Symbol值属性名数组

利用这个特性可以将其用于为对象定义一些非私有但又只希望用于内部的方法。

1.4 Symbol.for()、Symbol.keyFor()

有时候我们希望能够重新使用同一个Symbol

Symbol.for(name)方法会搜索是否有name名称Symbol值,若有则返回这个值,若无则新建并返回一个以name名称的值

注意:这个名称是被登记在全局环境中供搜索的(不在值的身上),同时会赋给其描述属性

let s1 = Symbol('666')
let s2 = Symbol.for('666')
let s3 = Symbol.for('666')

s1 == s2; //false
s2 == s3; //true

Symbol.keyFor(s)方法可以返回Symbol值登记在全局的名称,若未登记会返回undefined

2. Set和Map数据结构

2.1 Set

2.1.1 基本用法

Set为集合,成员的值都是唯一的,没有重复。

let s = new Set();
for (let t of [1,2,3,3,3]) s.add(t);

let s = new Set([1,2,3,3,3]); //传入可迭代数据进行初始化
s.size; //3

所以可以利用Set去重:[...new Set(arr)]或者Array.from(new Set(arr))

其是否重复的判断依据类似===,但是不会认为NaN!==NaN

所以在内部不会有重复的NaN

此外,两个对象总是不相等的

2.1.2 属性、方法

Set实例有size属性,返回成员总数 有add(val), delete(val), has(val), clear()等方法

2.1.3 遍历

Set实例的keys()方法可以返回键迭代器(按添加顺序)

values()entries()方法也可以,但是键和值是相等

此外Set结构的实例默认可遍历,可以直接用for of遍历(默认使用values()生成迭代器)

2.2 Map

2.2.1 基本用法

Map数据结构类似于对象,但最大的好处是其不再局限于字符串,各种类型的值和对象都可以作为键,是一种更完善的Hash结构实现。

let m = new Map();
let o = {p:'foo'}

m.set(o, 'bar'); //o为键
m.get(o); // 'bar'
m.has(o); //true
m.delete(o); //true 删除失败会返回false

// 或者使用键值对数组进行构造
let m = new Map([
    ['name', 'baz'],
    ['age', 17],
    [233, '笑']
])
m.get(233); //'笑'
m.get(666); //undefined 不存在的键会返回undefined

注意:只有对同一个对象的引用,Map才认为是同一个键(其实就是Hash计算是根据对象引用来的)

值类型时,只要值严格相等就视为同一个键(比如0和-0,undefined和undefined,但是额外包括了NaN与NaN)

2.2.2 属性和方法

属性有: size 方法有: set(k,v), get(k), has(k), delete(k), clear()

2.2.3 遍历

keys(), values(), entries(), forEach() 顺序与插入顺序一致

默认迭代器entries()方法,可以直接使用for of遍历

m.forEach((k,v)=>console.log(k,v));

for (let [k,v] of m) console.log(k,v);