Symbol
出现的原因: 对象的属性容易重复,导致出现问题,Symbol的出现,解决了这个问题。 不能使用new 关键词 进行声明Symbol 属于原始类型 ,类似字符串的数据类型Symbol 接受一个参数 ,该参数属于对Symbol的描述 ,该参数暂时没有太多限制,参数只是描述 ,就算参数一致 ,但Symbol还是不一样 的。 Symbol 不能 与其他值进行 运算 (字符串拼接,或者是字符串模板也不可以) Symbol值可以 转字符串 以及布尔型 ,但不能转数值 (原因是第5条) Symbol的描述参数 可以使用description 进行展示出来。即 Symbol(‘foo’).description === ‘foo’ Symbol 作为对象属性名时,只能使用[],不能使用点 。属于公有属性,非私有属性 Symbol在对象中声明的属性,只能使用Object.getOwnPropertySymbols() ,ES6提供的一个新的Reflect.ownKeys()也可以获取 Symbol.for() 也是声明Symbol,不过 通过它声明,可以判断某些描述是否已经存在。 存在,返回对应的Symbol,否则就是创建 该方式声明的,可以在全局供搜索到。Symbol.keyFor() 能获取到 Symbol.for() 声明的Symbol的描述值
const s2 = Symbol. for ( 'foo' )
const foo = Symbol. keyFor ( s2)
console. log ( foo)
Symbol 内置的属性方法
Symbol.hasInstance 这个方法,在W3C上面说明的是, 指向一个内部方法,当其他对象使用 instanceof运算符,判断是否为该对象的实例时,会调用这个方法。 而后所给的例子,主要是用instanceof 去进行操作是否在对象中。 所以暂时得出的结论,这个方法是可以重写对象的instanceof的方法 。Symbol.isConcatSpreadable 属性等于一个布尔值,表示该对象用于 Array.prototype.concat()时,是否可以展开。Symbol.species 对象的Symbol.species 属性,指向一个构造函数。创建衍生对象时(例子:声明一个类,该类继承Array类,然后创建实例,该实例使用map方法生成一个新的数组实例,问:新的数组实例的原型指向谁?该新的数组实例属于衍生对象吗?),会使用该属性。不过,使用时,需要在类里面使用 get 放在前面(例子: get Symbol.species { return this }) 总之, Symbol.species 的作用在于,实例对象在运行过程中,需要再次调用自身的构造函数时,会调用该属性指定的构造函数。它主要的用途是,有些类库是在基类的基础上修改的,那么子类使用继承的方法时,作者可能希望返回基类的实例,而不是子类的实例。 Symbol.match 对象的 Symbol.match属性,指向一个函数。当执行str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值。(字符串的match方法)Symbol.replace 对象的Symbol.replace属性,指向一个方法,当该对象被String.prototype.replace方法调用时,会返回该方法的返回值。(字符串的replace方法)Symbol.search 对象的 Symbol.search 属性,指向一个方法,当该对象被 String.prototype.search 方法调用时,会返回该方法的返回值。(字符串的search)Symbol.split 对象的Symbol.split 属性,指向一个方法,当该对象被String.prototype.split方法调用时,会返回该方法的返回值。(字符串的split方法)Symbol.iterator 对象的Symbol.iterator属性,指向该对象的默认遍历器方法。(主要指向iterator,配合for…of 的使用)Symbol.toPrimitive 对象的Symbol.toPrimitive 属性,指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。Symbol.toPrimitive 被调用时,会接受一个字符串参数,表示当前运算的模式,一共有三种模式。Number, String, Default(可以转字符串,或者转数字)Symbol.toStringTag 对象的Symbol.toStringTag属性,指向一个方法。在该对象上面调用 Object.prototype.toString方法时,如果这个属性存在,它的返回值会出现在 toString 方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制 [object Object] 或 [object Array] 中 object 后面的那个字符串。
ES6 新增内置对象的 Symbol.toStringTag 属性值如下: JSON[Symbol.toStringTag] :‘JSON’ Math[Symbol.toStringTag] :‘Math’ Module 对象 M[Symbol.toStringTag] :‘Module’ ArrayBuffer.prototype[Symbol.toStringTag] :‘ArrayBuffer’ DataView.prototype[Symbol.toStringTag] :‘DataView’ Map.prototype[Symbol.toStringTag] :‘Map’ Promise.prototype[Symbol.toStringTag] :‘Promise’ Set.prototype[Symbol.toStringTag] :‘Set’ %TypedArray%.prototype[Symbol.toStringTag] :'Uint8Array’等 WeakMap.prototype[Symbol.toStringTag] :‘WeakMap’ WeakSet.prototype[Symbol.toStringTag] :‘WeakSet’ %MapIteratorPrototype%[Symbol.toStringTag] :‘Map Iterator’ %SetIteratorPrototype%[Symbol.toStringTag] :‘Set Iterator’ %StringIteratorPrototype%[Symbol.toStringTag] :‘String Iterator’ Symbol.prototype[Symbol.toStringTag] :‘Symbol’ Generator.prototype[Symbol.toStringTag] :‘Generator’ GeneratorFunction.prototype[Symbol.toStringTag] :‘GeneratorFunction’ Symbol.unscopables 对象的Symbol.unscopables 属性,指向一个对象。该对象指定了使用 with关键字时,哪些属性会被 with 环境排除。 例子: 代码通过指定Symbol.unscopables属性,使得 with 语法块不会在当前作用域寻找 foo 属性,即 foo 将指向外层作用域的变量。
class Even {
static [ Symbol. hasInstance] ( obj ) {
return Number ( obj) % 2 === 0 ;
}
}
const Even = {
[ Symbol. hasInstance] ( obj ) {
return Number ( obj) % 2 === 0 ;
}
} ;
1 instanceof Even
2 instanceof Even
12345 instanceof Even
let arr1 = [ 'c' , 'd' ] ;
[ 'a' , 'b' ] . concat ( arr1, 'e' )
arr1[ Symbol. isConcatSpreadable]
let arr2 = [ 'c' , 'd' ] ;
arr2[ Symbol. isConcatSpreadable] = false ;
[ 'a' , 'b' ] . concat ( arr2, 'e' )
let obj = { length : 2 , 0 : 'c' , 1 : 'd' }
obj[ Symbol. isConcatSpreadable] = true
[ 'a' , 'b' ] . concat ( obj, '1' )
class MyClass extends Array {
}
const a = new MyClass ( [ 1 , 2 , 3 ] )
const b = a. map ( item => item* 2 )
const c = b. filter ( item => item === 4 )
b instanceof MyClass
c instanceof MyClass
class MyArray extends Array {
static get [ Symbol. species] ( ) {
return Array
}
const d = new MyArray ( [ 1 , 2 , 3 ] )
const e = d. map ( item => item* 2 )
e instanceof MyArray
e instanceof Array
String . prototype. match ( regexp)
regexp[ Symbol. match] ( this )
class MyMatcher {
[ Symbol. match] ( string ) {
return 'hello world' . indexOf ( string) ;
}
}
'e' . match ( new MyMatcher ( ) )
class Collection {
* [ Symbol. iterator] ( ) {
let i = 0 ;
while ( this [ i] !== undefined ) {
yield this [ i] ;
++ i;
}
}
}
let myCollection = new Collection ( ) ;
myCollection[ 0 ] = 1 ;
myCollection[ 1 ] = 2 ;
for ( let value of myCollection) {
console. log ( value) ;
}
let obj = {
[ Symbol. toPrimitive] ( hint ) {
switch ( hint) {
case 'number' :
return 123 ;
case 'string' :
return 'str' ;
case 'default' :
return 'default' ;
default :
throw new Error ( ) ;
}
}
} ;
2 * obj
3 + obj
obj == 'default'
String ( obj)
( { [ Symbol. toStringTag] : 'Foo' } . toString ( ) )
class Collection {
get [ Symbol. toStringTag] ( ) {
return 'xxx' ;
}
}
let x = new Collection ( ) ;
Object . prototype. toString . call ( x)
class MyClass {
foo ( ) { return 1 ; }
}
var foo = function ( ) { return 2 ; } ;
with ( MyClass . prototype) {
foo ( ) ;
}
class MyClass {
foo ( ) { return 1 ; }
get [ Symbol. unscopables] ( ) {
return { foo : true } ;
}
}
var foo = function ( ) { return 2 ; } ;
with ( MyClass . prototype) {
foo ( ) ;
}