ES6引入了一种新的原始数据类型Symbol,表示读一无二的值,它是js语言的第七种数据类型,前六种undefined、null、Boolean、String、Number、Object
Symbol值通过Symbol函数生成,这就是说对象的属性名现在可以有两种数据类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。凡是属性名属于Symbol类型,就都属于独一无二的,这样保证不会与其他属性名产生冲突
Symbol函数不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象
Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转为字符串,比较容易区分
如果Symbol的参数是一个对象,就会调用该对象的toString方法,将其转为字符串,然后才生成一个Symbol值
Symbol函数的参数只是表示对当前Symbol值得秒搜狐,因此相同参数的Symbol函数的返回值实不相等的
Symbol值不能与其他类型的值进行运算,会报错,但是可以显式地转为字符串也可以转为数值
作为属性名的Symbol
每一个Symbol值都是不相等,这意味着Symbol值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性。
不能用点运算符
在对象内部,使用Symbol值定义属性时,Symbol值必须放在方括号之中
魔术字符串:在代码多次多次出现、与代码形成强耦合的某一个具体的字符串或者数值
属性名的遍历
Symbol作为属性名,该属性不会出现在for...in、for...of循环中。但是,它也不是私有属性,有一个Object.getOwnPropertySymbols方法,可以获取指定对象所有的Symbol属性名。Object.getOwnPropertySymbols方法返回一个数组,成员是当前对象的所有用作属性名的Symbol值
reflect.ownKeys方法返回所有类型的键名,包括常规键名和Symbol键名
由于Symbol值作为名称的属性,不会被常规方法遍历得到。我们可以利用这个特性,为对象定义一些非私有的但又希望只用于内部的方法
5、Symbol .for,Symbol.keyFor()
Symbol.for方法可以做到重新使用用一个Symbol值。
Symbol.for()与Symbol()这两种写法,都会生成新的Symbol。它们的区别是,前者会被登记在全局环境中供搜索,后者不会。Symbol.for()不会每次调用就会返回一个新的SYmbol类型的值,而是会先检查给定的key是否已经存在,如果不存在才会新建一个值
Symbol.keyFor方法返回一个已登记的Symbol类型值的key
6、实例:模块Singleton模式
Singleton模式指的是调用一个类,任何时候返回的都是同一个实例
7、内置的Symbol值
除了定义自己使用的Symbol值以外,ES6提供了11个内置的Symbol值,指向语言内部使用的方法
1)Symbol.hasInstance属性,指向一个内部方法。当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法
2)Symbol.isConcatSpreadable
对象的Symbol.isConcatSpreadable属性等于一个布尔值,表示该对象使用Array.prototype.concat()时,是否可以展开
3)Symbol.species
对象的Symbol.species属性,指向当前对象的构造函数。创造实例时,默认会调用这个方法,即使用这个属性返回的函数当做构造函数来创造新的实例对象
4)Symbol.match()
指向一个函数,当执行str.match(myObject)时,如果该属性存在,会用它,返回该方法的返回值
5)Symbol.replace
对象的Symbol.replace属性,指向一个方法,当该对象被String.prototype.replace方法调用时,会返回该方法的返回值
6)Symbol.search()
指向一个方法,当该对象被String.prototype.search方法调用时,会返回该方法的返回值
7)Symbol.split
Symbol.split属性,指向一个方法,当该对象被String.prototype.split方法调用时,会返回该方法的返回值
8)Symbol.iterator
独享的Symbol.iterator属性,指向该对象的默认遍历器方法
9)Symbol.toPrimitive
对象的Symbol.toPrimitive属性,指向一个方法.该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值
10)Symbol.toStringTag
对象的Symbol.toStringTag属性,指向一个方法
11)Symbol.unscopables
对象的Symbol.unscopables,指向一个对象。该对象指定了使用with关键字时,哪些属性会被with环境排除
Set和Map数据结构
ES6提供了新的数据结构Set,它类似于数组,
但是成员的值都是唯一的,没有重复的值
Set本身是一个构造函数,用来生成Set数据结构
Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化。
还可以接受类似数组的对象作为参数
向Set加入值得时候,不会发生类型转换。Set内不许判断两个值是否不同,使用的算法叫做“Same-value equality”它类似于与精确相等运算符,主要的区别是NaN等于自身,而精确相等运算符认为NaN不等于自身
另外两个对象总是不相等的
1)Set实例的属性和方法
属性:
-Set.prototype.constructor:构造函数,默认就是Set函数
-Set.prototype.size:返回Set实例的成员的总数
方法:(操作方法和遍历方法)
操作方法:add(value)、delete(value)、has(value)、clear()
Array.from方法可以将Set结构转为数组
遍历方法:
keys()返回键名的遍历器;values()返回键值得遍历器;entries()返回键值对的遍历器,只有键值(键名和键值是同一个值,所以keys方法和values方法的行为完全一致)
forEach()使用回调函数遍历每个成员。由于Set结构没有键名,Set结构的实例的forEach方法,用于对每个成员执行某种操作,没有返回值。
扩展运算符和Set结构相结合,就可以去除数组的重复成员
数组的map结构和filter方法也可以用于Set
如果想在遍历操作中,同步改变原来的Set结构,目前没有直接的方法,但又两种变通方法。一种是利用原Set结构映射出一个新的结构,然后复制给原来的Set结构;另一种是利用Array.from方法
2、WeakSet
WeakSet结构与Set类似,也是不重复的值得结合。但是,它与Set有两个区别,首先,WeakSet的成员只能是对象,而不能是其他类型的值
WeakSet中的对象都是弱引用,即垃圾回收机制不考虑WeakSet对该对象的引用,也就是说,如果如果其他对象都不在引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在与WeakSet之中
语法:
const ws = new WeakSet()。WeakSet是一个勾走函数,可以使用new命令,创建WeakSet数据结构
WeakSet可以接受一个数组或类似数组的对象作为参数。
WeakSet不能遍历,是因为成员都是弱引用
3、Map
键值对的键只接受键作为键名,ES6提供了Map数据结构,Object结构提供了“字符串--值”的对应,Map结构提供了“值--值”的对应。
Map构造函数接受数组作为参数,不仅仅是数组,任何具有Iterator接口的数据结构都可以当做Map构造函数的参数,这就是说Set和Map都可以用来生成新的Map。
实例的属性和操作方法
属性:size属性;set(key,value)set方法设置键名key队形的键值为value,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就生成该键
set方法返回的是当前的Map对象,因此可以采用链式写法
get(key)方法读取key对应的键值,如果找不到key,返回undefined
has方法返回一个布尔值,表示某个值是否在当前Map对象之中。
delete(key)delete方法删除某个键,返回true。如果删除失败,返回false
clear方法清除所有成员,没有返回值
遍历方法:
Map结构原生提供三个遍历器和生成函数和一个遍历方法
-keys()返回键名的遍历器;values()返回键值得遍历器;-entries()返回所有成员的遍历器;forEach()遍历Map的所有成员
上面代码最后的那个例子,表示Map结构的默认遍历器接口,就是entries方法
Map结构转为数组结构,比较快速的方法是使用扩展运算符
与其他数据结构的互相转换
1)Map转为数组(使用扩展运算符...)
2)数组转为Map
将数组传入Map构造函数,就可以转为Map
new Map([
[true,7],
[{foo:3},['abc']]
])
3)Map转为对象,如果所有Map的键都是字符串,它可以转为对象。
4)对象转为Map
5)Map转为JSON,分为两种情况,一种情况是,Map的键名都是字符串,这是可以选择为对象JSON
另一种情况是,Map的键名有非字符串,这是可以算则转为数组JSON
6)JSON转为Map
4、WeakMap
Weak结构与Map结构类似,也是用于生成键值对的结合
WeakMap与Map的区别
WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名