Symbol

作者: della岳 | 来源:发表于2022-02-08 15:39 被阅读0次

    Symbol 独一无二的值,一种新的原始数据类型,类似于一种特殊字符串。

    声明

    声明时可传入描述值,通过description读取描述值

    1. 声明方式一,Symbol(...)
    slet s1 = Symbol(); 
    let s2 = Symbol(); 
    console.log(s1); //Symbol()
    console.log(s2); //Symbol()
    console.log(s1 === s2); //false ,返回的字符串一样但是不相等
     //声明时传入字符串,就能知道当前是哪一个Symbol
    let s3 = Symbol('foo'); 
    let s4 = Symbol('bar'); 
    console.log(s3); //Symbol(foo)
    console.log(s4); //Symbol(bar)
    console.log(s3 === s4); //false 
    console.log(s4.description); //foo ,打印描述值,就是声明时传入的值
    

    如果传入的是对象时,会返回对象的toString()值显示

    let obj = {
        name : 'yolin',
    }
    let s1 = Symbol(obj)
    console.log(s1) //Symbol([object Object])
    obj.toString = function(){ //添加一个toString方法
        return this.name
    }
    let s2 = Symbol(obj)
    console.log(s2) //Symbol(yolin)
    
    1. 声明方式二,Symbol.for(...)。用Symbol.for去声明时,会登记到全局,会先去全局中找有没有一样的描述,如果有就直接返回那个一样的给它,而不会去重新声明一个Symbol
    const s1 = Symbol.for('foo');
    const s2 = Symbol.for('foo');
    console.log(s1 === s2) //true
    
    1. Symbol.keyFor 用来判断这个Symbol是否有登记到全局,用Symbol.for声明的就会登记到全局,并返回描述值
    const s3 = Symbol('foo');
    console.log(Symbol.keyFor(s3)) //undefined
    console.log(Symbol.keyFor(s1)) //foo
    

    应用场景

    场景1,用姓名作为key,用Symbol属性避免重名覆盖

    const st1 = '李四';
    const st2 = '李四';
    const grade  = {
        [st1]:{address:'xxx',tel:1111},
        [st2]:{address:'xxx',tel:2222},
    }
    console.log(grade);//第一个李四被第二个李四覆盖
    

    对象的属性名同名时,会自动覆盖上一个。要想同名的信息不被覆盖,可以使用Symbol值作为属性名

    const st1 = Symbol('李四');
    const st2 = Symbol('李四');
    const grade = {
        [st1]: { address: 'xxx', tel: 1111 },
        [st2]: { address: 'xxx', tel: 2222 },
    }
    console.log(grade);//使用symbol不会覆盖,因为symbol是唯一的,尽管描述值一样
    console.log(grade[st1]);//读取第一个李四信息
    console.log(grade[st2])//读取第二个李四信息
    

    2、Symbol属性在一定程度上会被保护起来,使用特殊遍历方法才能遍历到symbol属性,Reflect.ownKeys()

    const sym = Symbol('imooc');
    class User {
        constructor(name) {
            this.name = name;
            this[sym] = 'imooc.com';
        }
        getName() {
            return this.name + ' ' + this[sym]
        }
    }
    const user = new User('della');
    console.log(user)
    console.log(user.getName())
    // 遍历user属性
    for (let key in user) {//读不到symbol属性
        console.log(key)
    }
    for (let key of Object.keys(user)) {//读不到symbol属性
        console.log(key)
    }
    for (let key of Object.getOwnPropertySymbols(user)) {//读symbol属性
        console.log(key)
    }
    for (let key of Reflect.ownKeys(user)) {//既能读到普通属性,又能读到symbol属性
        console.log(key)
    }
    

    3、应用场景二,消除魔术字符串

    function getArea(shape) {
        let area = 0;
        switch (shape) {
            case 'Triangle':
                area = 1;
                break;
            case 'Circle':
                area = 2;
                break;
        }
        return area
    }
    console.log(getArea('Triangle'))//获取三角形面积
    

    用对象属性名消除魔术字符串

    const shapeType = {
        triangle: Symbol(),//属性值并不重要
        circle: Symbol()
    }
    function getArea(shape) {
        let area = 0;
        switch (shape) {
            case shapeType.triangle:
                area = 1;
                break;
            case shapeType.circle:
                area = 2;
                break;
        }
        return area
    }
    console.log(getArea(shapeType.triangle))//获取三角形面积
    console.log(getArea(shapeType.circle))//获取三角形面积
    

    相关文章

      网友评论

          本文标题:Symbol

          本文链接:https://www.haomeiwen.com/subject/rguahrtx.html