• JavaScript Symbol


    Symbol

      Symbol对象是es6中新引进的一种数据类型,它的作用非常简单,就是用于防止属性名冲突而产生。

      Symbol的最大特点就是值是具有唯一性,这代表使用Symbol类型的值能做独一无二的一些事情。

      此外,Symbol没有构造函数,这使得我们不能new它,直接使用即可。

    基础知识

    声明Symbol

      使用Symbol()声明一个独一无二的值。

    <script>"use strict";
    
            let Sym1 = Symbol();  // 独一无二的值
            let Sym2 = Symbol();
    
            console.log(typeof Sym1);  // symbol
    
            console.log(Sym1 == Sym2);  // false
    </script>

    描述信息

      Symbol的值在声明时添加一段描述信息。

      使用description属性可查看描述信息。

      注意:即使两个Symbol的描述信息是一样的也不会有什么问题,因为它仅仅是描述信息而已。

    <script>"use strict";
    
            let Sym1 = Symbol("这是Sym1的描述信息");  // 独一无二的值
            let Sym2 = Symbol("这是Sym2的描述信息");
    
            console.log(Sym1.description);  // 这是Sym1的描述信息
            console.log(Sym2.description);  // 这是Sym2的描述信息
     
    </script>

    Symbol.for

      使用Symbol()来创建值不会进行记录,所以无论值看起来是否一样都不会引用同一份内存地址。

      而使用Symbol.for()来创建值则会进行记录,下次再创建相同的值时会直接引用记录的内存地址。

    <script>"use strict";
    
            let Sym1 = Symbol("测试");  // 独一无二的值
            let Sym2 = Symbol("测试");
    
            console.log(Sym1 == Sym2);  // false
    </script>
    <script>"use strict";
    
            let Sym1 = Symbol.for("测试");  // 将这个值的内存地址记录,下次再创建时直接引用内存地址
            let Sym2 = Symbol.for("测试");
    
            console.log(Sym1 == Sym2);  // true
    </script>

    Symbol.keyFor

      用于返回由Symbol.for()创建的值的描述信息。

      如果值没有描述信息则返回undefined

      当然,我们也可以使用description属性来获取描述信息,二者皆可。

    <script>"use strict";
    
            let Sym1 = Symbol.for("测试");  // 将这个值的内存地址记录,下次再创建时直接引用内存地址
            let Sym2 = Symbol.for();
    
            console.log(Symbol.keyFor(Sym1));  // 测试
            console.log(Symbol.keyFor(Sym2));  // undefined
    
            console.log(Sym1.description);  // 测试
            console.log(Sym2.description);  // undefined
    </script>

    实际应用

    对象属性

      Js中的对象(键)如果直接声明就会变成String类型,这在某些程度上可能会引起对象属性冲突问题。

      对象的键最好是唯一的,Symbol类型的值无疑是最好的选择。

      当我们给想对象的键设置为Symbol类型的值的时候需要注意2点问题。

      Symbol声明和访问使用 [](变量)形式操作

      不能使用 . 语法因为 .语法是操作字符串属性的

    <script>"use strict";
    
            let username = Symbol(); 
            let age = Symbol();
    
            let dic = {  // 声明时加上 []  否则会变成String类型  --> "username"
                    [username]:"云崖",
                    [age]:18,
            };
    
            // 不能使用 . 语法获取值(属性)
            console.log(dic[username]);  // 云崖
    
            console.log(dic[age]);  // 18
    </script>

    对象遍历

      Symbol类型值不能被 for/infor/of 遍历操作找到。

      以下示例可以看出,找不到两个Symbol类型的键。

    <script>"use strict";
    
            let username = Symbol();  
            let age = Symbol();
    
            let dic = {  // 声明时加上 []  否则会变成String类型  --> "username"
                    [username]: "云崖",
                    [age]: 18,
                    "gender": "男",
            };
    
            for (let i in dic) {
                    console.log(i);  // gender
            }
    
            // for/of 只能遍历一个迭代对象,不能直接遍历对象。所以我们使用Object.keys(dic)将dic转换为一个迭代对象。
            for (let i of Object.keys(dic)) {
                    console.log(i);  // gender
            }
    
    </script>

      可以使用 Object.getOwnPropertySymbols 获取所有Symbol属性(键)。

      注意,这是仅仅获取Symbol的属性(键)。

    <script>"use strict";
    
            let username = Symbol(); 
            let age = Symbol();
    
            let dic = {  // 声明时加上 []  否则会变成String类型  --> "username"
                    [username]: "云崖",
                    [age]: 18,
                    "gender": "男",
            };
    
            for (let i in Object.getOwnPropertySymbols(dic)) {
                    console.log(i);  // 0 1
            }
    
            // for/of 只能遍历一个迭代对象,不能直接遍历对象。所以我们使用Object.keys(dic)将dic转换为一个迭代对象。
            for (let i of Object.getOwnPropertySymbols(dic)) {
                    console.log(i);  // (2) Symbol()
            }
    
    </script>

      也可以使用 Reflect.ownKeys(obj) 获取所有属性(键)包括Symbol类型的属性。

    <script>"use strict";
    
            let username = Symbol();  
            let age = Symbol();
    
            let dic = {  // 声明时加上 []  否则会变成String类型  --> "username"
                    [username]: "云崖",
                    [age]: 18,
                    "gender": "男",
            };
    
            for (let i in Reflect.ownKeys(dic)) {
                    console.log(i);  // 0 1 2
            }
    
            console.log("*".repeat(20));
    
            // for/of 只能遍历一个迭代对象,不能直接遍历对象。所以我们使用Object.keys(dic)将dic转换为一个迭代对象。
            for (let i of Reflect.ownKeys(dic)) {
                    console.log(i);  // gender (2) Symbol()
            }
    
    </script>

    私有属性

      我们可以使用Symbol不能被for/in以及for/of访问的特性,为类制作私有属性以及提供访问接口。

    <script>"use strict";
    
    
            const sex = Symbol("性别");
    
            class User {
    
                    constructor(name, age, gender) {
                            this[sex] = gender;  // 存入类对象中
                            this.name = name;
                            this.age = age;
                    }
    
                    getMsg() {
                            // 我们希望通过提供的API接口来让用户调出gender属性
                            return `姓名:${this.name},年龄:${this.age},性别:${this[sex]}`
                    }
            }
    
            let u1 = new User("云崖", 18, "男");
    
            console.log(u1.getMsg());  // 只能通过接口来拿到性别    姓名:云崖,年龄:18,性别:男
    // 如果循环不管是for/in还是for/of都是拿不到性别的
    for (const i in u1) {
                    console.log(i);
                    //  name
                    //  age
    
            }
    
    </script>

     

  • 相关阅读:
    【Spring注解驱动开发】二狗子让我给他讲讲@EnableAspectJAutoProxy注解
    【Spring注解驱动开发】你敢信?面试官竟然让我现场搭建一个AOP测试环境!
    【Nginx】如何基于主从模式搭建Nginx+Keepalived双机热备环境?这是最全的一篇了!!
    华为分析+App Linking:一站式解决拉新、留存、促活难
    deeplink跳转快应用返回出现两次系统添加桌面的弹框
    4月26日19:30,#HMS Core Insights#直播系列第二期来了!
    HMS Toolkit自动化环境配置,助您高效集成HMS Core
    全体注意!一大波鸿蒙三方库即将到来
    HMS Toolkit助力开发者高效集成HMS Core
    教你使用一套代码解决出海问题
  • 原文地址:https://www.cnblogs.com/Yunya-Cnblogs/p/13397110.html
Copyright © 2020-2023  润新知