全面认识ES6(二)
2017-08-02 09:47
176 查看
Symbol
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是
JavaScript 语言的第七种数据类型,前六种是:
undefined、
null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
Symbol 值通过
Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的
Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
let s = Symbol(); typeof s // "symbol"
上面代码中,变量
s就是一个独一无二的值。
typeof运算符的结果,表明变量
s是
Symbol 数据类型,而不是字符串之类的其他类型。
注意,
Symbol函数前不能使用
new命令,否则会报错。这是因为生成的
Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。
Symbol函数可以接受一个字符串作为参数,表示对
Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
var s1 = Symbol('foo'); var s2 = Symbol('bar'); s1 // Symbol(foo) s2 // Symbol(bar) s1.toString() // "Symbol(foo)" s2.toString() // "Symbol(bar)"
上面代码中,
s1和
s2是两个
Symbol 值。如果不加参数,它们在控制台的输出都是
Symbol(),不利于区分。有了参数以后,就等于为它们加上了描述,输出的时候就能够分清,到底是哪一个值。
如果 Symbol 的参数是一个对象,就会调用该对象的
toString方法,将其转为字符串,然后才生成一个
Symbol 值。
const obj = { toString() { return 'abc'; } }; const sym = Symbol(obj); sym // Symbol(abc)
注意,
Symbol函数的参数只是表示对当前
Symbol 值的描述,因此相同参数的
Symbol函数的返回值是不相等的。
// 没有参数的情况 var s1 = Symbol(); var s2 = Symbol(); s1 === s2 // false // 有参数的情况 var s1 = Symbol('foo'); var s2 = Symbol('foo'); s1 === s2 // false
上面代码中,
s1和
s2都是
Symbol函数的返回值,而且参数相同,但是它们是不相等的。
Symbol 值不能与其他类型的值进行运算,会报错。
var sym = Symbol('My symbol'); "your symbol is " + sym // TypeError: can't convert symbol to string `your symbol is ${sym}` // TypeError: can't convert symbol to string
但是,Symbol 值可以显式转为字符串。
var sym = Symbol('My symbol'); String(sym) // 'Symbol(My symbol)' sym.toString() // 'Symbol(My symbol)'
另外,Symbol 值也可以转为布尔值,但是不能转为数值。
var sym = Symbol(); Boolean(sym) // true !sym // false if (sym) { // ... } Number(sym) // TypeError sym + 2 // TypeError
Set和Map数据结构
Set 本身是一个构造函数,用来生成 Set 数据结构。const s = new Set(); [2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x)); for (let i of s) { console.log(i); } // 2 3 5 4
上面代码通过
add方法向
Set 结构加入成员,结果表明 Set 结构不会添加重复的值。
Set 函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。
// 例一 const set = new Set([1, 2, 3, 4, 4]); [...set] // [1, 2, 3, 4] // 例二 const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]); items.size // 5 // 例三 function divs () { return [...document.querySelectorAll('div')]; } const set = new Set(divs()); set.size // 56 // 类似于 divs().forEach(div => set.add(div)); set.size // 56
上面代码中,例一和例二都是
Set函数接受数组作为参数,例三是接受类似数组的对象作为参数。上面代码中,也展示了一种去除数组重复成员的方法。
为了解决这个问题,ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
const m = new Map(); const o = {p: 'Hello World'}; m.set(o, 'content') m.get(o) // "content" m.has(o) // true m.delete(o) // true m.has(o) // false
上面代码使用 Map 结构的
set方法,将对象
o当作
m的一个键,然后又使用
get方法读取这个键,接着使用
delete方法删除了这个键。
上面的例子展示了如何向 Map 添加成员。作为构造函数,Map 也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。
const map = new Map([ ['name', '张三'], ['title', 'Author'] ]); map.size // 2 map.has('name') // true map.get('name') // "张三" map.has('title') // true map.get('title') // "Author"
上面代码在新建 Map 实例时,就指定了两个键
name和
title。
Map构造函数接受数组作为参数,实际上执行的是下面的算法。
const items = [ ['name', '张三'], ['title', 'Author'] ]; const map = new Map(); items.forEach( ([key, value]) => map.set(key, value) );
事实上,不仅仅是数组,任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构(详见《Iterator》一章)都可以当作
Map构造函数的参数。这就是说,
Set和
Map都可以用来生成新的
Map。
const set = new Set([ ['foo', 1], ['bar', 2] ]); const m1 = new Map(set); m1.get('foo') // 1 const m2 = new Map([['baz', 3]]); const m3 = new Map(m2); m3.get('baz') // 3
上面代码中,我们分别使用 Set 对象和 Map 对象,当作
Map构造函数的参数,结果都生成了新的
Map 对象。
相关文章推荐
- 全面认识ES6(一)
- 全面认识JUnit 4的新特征
- 全面接触TDD - 2. Unit Test中的一些基本观点与概念及NUint的初步认识
- 全面认识JUnit 4的新特征
- 全面认识Cookie
- 全面认识Android手机 (MIUI ROM适配之旅第一天——认识Android手机 )
- 全面认识JAVA
- 认识全面的NULL(摘抄)
- 全面认识UML-类图元素(java)
- 全面认识APM和ACPI
- 全面认识***
- 认识全面的null
- 全面认识JAVA
- 全面认识网络诊断命令功能与参数——netsh diagnostic命令
- 全面认识Android手机(MIUI ROM适配之旅第二天——准备工作)
- 全面认识Android手机 (MIUI ROM适配之旅第一天——认识Android手机 )
- 全面认识敏捷建模思想(4)
- 全面深入认识C变量
- 全面认识UML类图元素