代码改变世界

Symbol

2019-03-04 21:34  思雯  阅读(306)  评论(0)    收藏  举报

一.原因

1.1    从根本上防止属性名的冲突,保证每个属性名称都是独一无二的,

由原来的6种数据结构 undefined null Boolean String Number Object 扩展一个Symbol

let demo1=Symbol()
console.log(typeof  demo1) //symbol 

1.2     注意事项

    (1)Symbol前不能使用new 会报错  它是类似字符串的数据类型  无法添加属性

    (2)Symbol函数可以接受一个字符串作为参数 主要来描述Symbol实例 在控制台种能够区分

    (3)如果参数是对象  就会调用对象的toString方法 生成一个Symbol

    (4)即使两个参数相同Symbol的返回值也是不相等的

    (5)Symbol值不能与其他值进行运算 会报错   console.log("string"+symbol) 都会报错

    (6)可以显式的转成字符串

    (7)可以转成布尔值,但不能转为数值(Number(stmbol)//会报错)

    (8)不能使用,运算符号取到定义的属性值 (例如xx.mySymbol  )

let mySymbol=Symbol(
      {
        a:10 ,
        toString(){
            return 'x'
        }
     })  //Symbol[x]   注意事项(3)
 console.log("xxxx"+mySymbol)//Cannot convert a Symbol value to a string  
//注意事项(5)
let a={}
let mySymbol=Symbol() a[mySymbol]
='hello' console.log(a.mySymbol)//undefined
a.mySymbol='mytest'
console.log(a.mySymbol)//mytest console.log(a[mySymbol])//hello

 

二.作为属性名的symbol基础用法

let a={}
let mySymbol=Symbol();a[mySymbol]='hello' //第一种
let a={ [mySymbol]:'hello'}//第二种
Object.defineProperty(a,mySymbol,{value:'hello'})//第三种

三 如何取值

3.1 不会出现在for...in,for...of循环种也不会Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回

3.2 同时也不是私有属性(Object.getOwnPropertyNames(obj)获取不到),有一个Object.getOwnPropertySymbols方法,可以获取指定对象的所有 Symbol 属性名。

3.3 Reflect.ownKeys(obj4) 可以获取obj4种的所有symbol值(数组) 
3.4 由于以 Symbol 值作为名称的属性,不会被常规方法遍历得到。我们可以利用这个特性,为对象定义一些非私有的、但又希望只用于内部的方法。

 

let obj4={}
let a4=Symbol('a')
let b4=Symbol('b')
obj4.c='c'
obj4[a4]='hello';
obj4[b4]='world'
let objSymbol4=Object.getOwnPropertySymbols(obj4)  //3.2的demo 获取所有Symbol
objSymbol4.forEach((item)=>{
     console.log(item);//Symbol(a), Symbol(b)
})
console.log(Reflect.ownKeys(obj4))//(3) ["c", Symbol(a), Symbol(b)]//获取包含Symbol的所有属性值   3.3的demo

四. Symbol.for(),Symbol.keyFor()

4.1 Symbol() 调用30个会返回30个 都不相同

4.2 Symbol.for() 会生成新的Symbol在全局中 如果存在则不创建,会返回那个 如果不存在则创建 调用30次只会返回一个 都相同  
 4.3 Symbol.keyFor() 参数是Symbol类型不是key 。返回已登记的 Symbol 类型值的key。 查找 Symbol.for()注册的 而 symbol(' ')的不算是

let temp5=Symbol('temp5')
let temp5_1=Symbol('temp5')
Symbol.keyFor(temp5)//undefined  说明Symbol.keyFor只能查询到到Symbol.for('temp5')这种定义 而查不到普通的Symbol('temp5')
let temp5_2=Symbol.for('temp5')
let temp5_3=Symbol.for('temp5')
Symbol.keyFor(temp5_2)//temp5        4.3的demo  
console.log(temp5==temp5_1)//false   4.1的demo   
console.log(temp5_1==temp5_2)//false
console.log(temp5==temp5_2)//false
console.log(temp5_2==temp5_3)//true  4.2的demo

五 实例:模块的 Singleton 模式

 const FOO_KEY = Symbol.for('foo');
 function A() 
{
this.foo = 'hello'; } if (!global[FOO_KEY]) { global[FOO_KEY] = new A(); } module.exports = global[FOO_KEY];

六  除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。

6.1 Symbol.hasInstance

  class MyClass{
            [Symbol.hasInstance](foo){
                return  foo instanceof  Array
            }
        }
   console.log([1,2,3] instanceof  new MyClass())//true

 6.2Symbol.replace

  对象的Symbol.replace属性,指向一个方法,当该对象被String.prototype.replace方法调用时,会返回该方法的返回值

Symbol.replace方法会收到两个参数,第一个参数是replace方法正在作用的对象,上面例子是Hello,第二个参数是替换后的值,上面例子是World。

 const x = {
        [Symbol.replace](...s){
            console.log(s)
        }
    };
    'Hello'.replace(x, 'World') // ["Hello", "World"]

 6.3.Symbol.species

有些类库是在基类的基础上修改的,那么子类使用继承的方法时,作者可能希望返回基类的实例,而不是子类的实例。

    class T1 extends Promise {
    }
    class T2 extends Promise {
        static get [Symbol.species]() {
            return Promise;
        }
    }
    console.log("demo9")
 console.log(new T1((r=>r())).then(v=>v) instanceof T1)//true
console.log(new T2((r=>r())).then(v=>v) instanceof T2)//false

6.4等等