Symbol 是ES6引入的一种新的原始数据类型,由于Symbol是一个原始类型的值,不是对象,不能添加属性.基本上
是一种类似于字符串的数据类型
概述
Symbol 可以接受一个字符串作为参数,主要是为了容易区分
Symbol 函数的参数只是对当前Symbol的描述,相同参数的Symbol返回值是不相同的
Symbol 值不能与其他类型的值进行运算(字符串的加运算)
Symbol 可以转字符串,布尔值
var sys =Symbol() // Symbol()
sys.toString() // "Symbol()"
Boolean(sys) //true
!sys //false
作为属性名的Symbol
由于每一个Symbol都是不相同的 意味Symbol值可以作为标识符用于对象的属性名,保证不会出现同名的属性
var mySymbol = Symbol()
1.
var a ={}
a[mySymbol]='hello'
2.
var a ={[mySymbol]:'hello'}
3.
var a = {}
object.defineProperty(a,mySymbol,{value:'hello'})
* Symbol值作为属性名的时候,不能使用点选运算符,因为点运算符后面总是字符串,所以实际的属性名是一个字符串
而不是Symbol值.同理,Symbol值在对象里的时候必须放在[]符号内
eg1:
const COLOR_RED =Symbol()
const COLOR_GREEN =Symbol()
function tes1t(color){
switch(color){
case COLOR_RED:
return COLOR_GREEN;
case COLOR_RED:
return COLOR_GREEN;
default:
throw new Error('undefined color')
}
}
eg2:
const obj={
DEBUGGER:Symbol('debugger')
}
魔术字符串
魔术字符串是指在代码中多次出现、与代码形成强耦合的某一个具体字符串或者数值
var shapeType={triangle:'triangle'}
function getArea(shape,options){
var area=0
switch(shape){
case shapeType.triangle:
area=1*options.height*options.width
break
}
return area
}
var shapeType={triangle:Symbol()}
function getArea(shape,options){
var area=0
switch(shape){
case shapeType.triangle:
area=1*options.height*options.width
break
}
return area
}
getArea(shapeType.triangle,{10,height:20}) //200
shapeType.triangle //Symbol()
Symbol.for,Symbol.keyFor()
Symbol.for
1.Symbol()[未登记的Symbol值]和Symbol.for()都会生成新的Symbol,区别在于前者会被登记在全局环境中供搜索
2.Symbol.for()不会每次调用都返回一个新的Symbol值,而是会在全局先检查给定的key是否已经
存在,如果不存在就新建一个,如果存在会返回同一个Symbol值
var s1 = Symbol('cat')
var s2 = Symbol('cat')
s1==s2 //false
var s1 = Symbol.for('cat')
var s2 = Symbol.for('cat')
s1==s2 //true
symbol.keyFor()
Symbol.keyFor() 方法返回一个已经登记的Symbol类型的key值
var s1 =Symbol.for('cat')
Symbol.keyFor(s1) //'cat'
var s1 =Symbol('cat')
Symbol.keyFor(s1) //undefined
var test = Symbol()
var test2=Symbol()
test1==test //false
// 使用Symbol.for(),可以重新使用一个Symbol值
var test1 = Symbol.for()
var test2 = Symbol.for()
test1===test2 //true
* Symbol.for 为Symbol值登记名字是全局环境的,可以在不同的iframe或service worker中获取
iframe = document.creatElement('iframe')
iframe.src = String(window.location)
document.body.appendChild(iframe)
iframe.contentWindow.Symbol.for('foo') ==Symbol.for('foo') //true
属性名的遍历
Object.getOwnPropertyNames()只能返回Symbol类型的键名
Reflect.ownkeys可以返回所有类型的键名
Symbol作为属性名的时候不会出现在for...in for...of循环中,也不会出现在Object.keys,Object.getOwnPropertyNames
返回,会被Object.getOwnPropertySymbols获取指定对象的所有用作属性名的Symbol值
var obj ={}
var a = Symbol('a')
var b = Symbol('b')
var objProperty = Object.getOwnPropertySymbols(obj)
obj // {Symbol(a): "hello", Symbol(b): "world"}
ObjProperty // [Symbol(a), Symbol(b)]
let obj ={}
let obj ={[Symbol('key')]:1,enum:2,nonEnum:3}
Reflect.ownKeys(obj) //["enum", "nonEnum", Symbol(key)]
以Symbol值作为名称的属性不会被常规遍历方法获得,可以利用这个特性,为独享定义一些私有但又只希望
内部使用的方法
var size = Symbol('size')
class Collection{
constructor(){
this[size]=0
}
add(item){
this[this[size]]=item
this[size]++
}
static sizeOf(instance){
return instance[size]
}
}
var x = new Collection() //Collection {Symbol(size): 0}
Collection.sizeOf(x) //0
x.add('foo') // Collection {0: "foo", Symbol(size): 1}
Collection.sizeOf(x) //1
Object.keys(x) // ['0']
Object.getOwnPropertyNames(x) //['1']
Object.getOwnPropertySymbols(x) //[Symbol(size)]
内置的Symbol值
Symbol.hasInstance
对象的Symbol.hasInstance属性指向内部一个方法,对象使用instanceOf运算符时会调用这个方法,判断对象是否是
某个构造函数的实例eg. foo instanceof Foo 在语言内部实际调用的是Foo[Symbol.hasInstance](foo)
Symbol.isConcatSpreadable
对象的Symbol.isConcatSpreadable属性等于一个布尔值,表示该对象使用Array.property.concat()时是否可以展开
let Arr1 = [1,2,3]
let Arr2 = [3,4]
var Arr3 = Arr1.concat(Arr2) //[1, 2, 3, 3, 2]
let Arr4 = [5,6]
Arr4[Symbol.isConcatSpreadable]= false
let Arr5 = Arr1.concat(Arr4) //[1, 2, 3, Array(2)]
Symbol.species
对象的Symbol.species属性指向一个方法对象创造实例的时候会调用this.constructor[Symbol.species]存在
就会使用这个属性作为构造函数来创建新的实例对象
Symbol,species属性默认的读取器如下
static get [Symbol.species](){
return this
}
Symbol.match
对象的Symbol.match属性指向一个函数,当执行str.match(myObject)时,如果改属性存在,会调用它返回该方法的返回值
String.property.macth(regexp)===>regexp[Symbol.macth](this)
Symbol.replace
对象的replace属性指向一个方法,当String.property.replace方法调用时会返回该方法的返回值
String.property.replace(searchValue,replaceValue) ==> searchValue[Symbol.replace](this,replaceValue)
Symbol.search
对象的Symbol.search属性指向一个方法,当对象被String.property.search方法调用时会返回该方法的返回值
String,property.search(regexp) ==> regexp[Symbol.search](this)
Symbol.split
对象的Symbol.split属性指向一个方法,当对象被String.property.split方法调用时会返回该方法的返回值
String,property.search(separator,limit) ==> regexp[Symbol.search](this,limit)
Symbol.iterator
对象的Symbol.split属性指向其默认的遍历器方法,即对象在进行for...of循环时调用这个方法,返回该对象的默认遍历器
Symbol.toPrimitive
对象的Symbol.toPrimitive属性指向一个方法,对象被转为原始类型的时候会调用这个方法,返回该对象对应的原始值