Symbol的简单理解

Symbol

1.Symbol 的意义

​ 之前我们的对象属性的数据类型都是字符串,没有其他的了。所以会导致属性名重复,导致属性值被覆盖的情况。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法,在添加的操作就很容易覆盖了原有的方法。所以需要一个独一无二的数据类型来完成这个使命。所以Symbol出来主持大局了。

2.Symbol的介绍

  1. 唯一性
    Symbol这个英文单词表示“唯一",它是Javascript的第七种数据类型(Number,String,Boolean,null,undefined,Object),表示它是唯一的。
    创建一个Symbol类型不需要用new操作符,否则会报错,因为生成的Symbol是一个原始类型的值,不是对象。直接let s = Symbol();测试s就是Symbol类型了。怎么说他是唯一的呢?

    let s = Symbol(); 
    let ss = Symbol(); 
    console.log(s == ss);	//false
    //或者
    let s = Symbol('a'); 
    let ss = Symbol('a'); 
    console.log(s == ss);//结果是false
    

    通过以上的比较,我们对Symbol的唯一性,有了一定的了解。也就是说当你创建了一个Symbol数据后,那么就是独一无二的存在了。

  2. 数据类型的修饰
    有人会好奇Symbol('a')里面的参数a又是怎么回事呢?字符串a表示一种修饰,对你当前创建的Symbol类型的一种修饰,作为区分使用,否则当你创建多个Symbol数据时,容易混淆。

    let s = Symbol('a'); 
    let ss = Symbol('a'); 
    console.log(s == ss);//false
    
  3. 与其他数据类型之间的转换
    Symbol不能用四则运算进行操作,否则报错。它只能用显式的方式转为字符串和布尔值,即:String(Symbol()) / Boolean(Symbol())

  4. 作为对象的属性

    • 作为对象的属性时,注意要用以下三种方式来书写:
    // 1. 作为对象的属性
    let hobby = Symbol("hobby");
    let level = Symbol("level");
    let sex = Symbol("sex");
    let person = {
        name: "小米",
        age: 21,
        [hobby]: "游泳"   //1.1
    }
    person[level] = "A"   // 1.2
    // 1.3
    Object.defineProperty(person,sex,{
        value: "男"
    })
    console.log(person.level);  //undefined
    console.log(person[hobby]); //游泳
    
    • 对象属性的创建

    以上说了对象属性的创建,但是我们要格外的注意,Symbol作为属性名,该属性不会出现在for...infor...of循环中,也不会被Object.keys()object.getOwnPropertyNames()JSON.stringify()返回。所以我们可以用Object.getOwnPropertySymbols方法,获取指定对象的所有Symbol属性名。
    看到这是不是感觉用Symbol类型创建的对象属性这么麻烦吗?如果一个对象里面有字符串的属性又有Symbol的属性,难不成要分来获取对象属性吗?答案是不用,那必须使用新的API方法:Reflect.ownKeys(),这个方法就可以返回对象所有的属性,也就是字符串属性和Symbol属性。所以这里要留意了。

    // 2.遍历迭代不出 以symbol命名的属性
    console.log(Object.keys(person));   //(2) ["name", "age"]
    
    console.log(Object.getOwnPropertySymbols(person));//(3) [Symbol(hobby), Symbol(level), Symbol(sex)]
    
    console.log(Object.getOwnPropertyNames(person));// ["name", "age"]
    
    // 解决:
    console.log(Reflect.ownKeys(person));// (5) ["name", "age", Symbol(hobby), Symbol(level), Symbol(sex)]
    
  5. Symbol.for()Symbol.keyFor()

    有时,我们希望重新使用同一个Symbol值,以上我们都说了Symbol数据类型是唯一的,所有只用Symbo()方法创建的Symbol类型是无法实现的。所有我们可以用Symbol.for()这个方法来实现。

    let s1 = Symbol.for("foo");
    let s2 = Symbol.for("foo");
    console.log(s1 === s2);     //true
    // 使用Symbol.for会在全局查找有没有和自己一样的存在,如果没有,就创建并在全局登记,如果在全局登记中有,则直接用已经登记创建过的。所以s1 === s2
    

    注意,这里的Symbol.for()Symbol()创建的都是Symbol类型,但是他们的创建机制有所不同,Symbol.for(a')的创建方式会在创建之前在全局中寻找,有没有用Symbol.for()的方式,并且key'a'的字符串创建了Symbol类型(创建了就会在全局中登记),如果有则不重复创建,直接用已创建的(已登记的)。然而Symbol("a')的创建是不会去检索全局的,是直接创建一个新的Symbol类型。这也是用Symbol(a')创建的两个Symbol类型不相等的根本原因。
    Symbol.keyFor()方法返回一个已登记的Symbol类型值的key

    let s1 = Symbol.for("foo");
    let s2 = Symbol.for("foo");
    let s3 = Symbol("foo");
    
    console.log(Symbol.keyFor(s1));// foo
    console.log(Symbol.keyFor(s2));// foo
    console.log(Symbol.keyFor(s3));// undefined
    // Symbol.keyFor返回一个已经登记的 Symbol类型的 key
    
posted @ 2021-09-08 09:59  青柠i  阅读(196)  评论(0编辑  收藏  举报