JavaScript Symbol对象

自闭症网瘾萝莉.ら 提交于 2020-10-09 04:22:16

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>

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!