ES6--Symbol的学习和使用

43 篇文章 0 订阅
5 篇文章 0 订阅

在面试过程中,会遇到有关Symbol的问题,所以学习了下:

<script>
//=======Symbol:
        //Symbol是由ES6规范引入的一项新特性,是一种新的基础数据类型,它的功能类似于一种标识唯一性的ID。
        //通常情况下,我们可以通过调用Symbol()函数来创建一个Symbol实例,用来表示独一无二的值,是一种原始数据类型。
        let x = Symbol();
        console.log(typeof x);  //symbol
        // Symbol函数可以接受字符串为参数,表示对Symbol实例的描述。为在控制台输出,或者转换为字符串时,比较容易区分.
        let s2 = Symbol('another symbol')
        // ES2019提供了一个属性description,直接返回Symbol的描述
        // Symbol值都是不相等的,意味着Symbol值可以作为标识符,用于对象的属性名,就可以保证不会出现同名的属性
        let s3 = Symbol('another symbol')
        console.log(s3 === s2); //false
        // Symbol作为对象的属性名时,不能用点运算符,要使用[]
        let a = Symbol();
        let obj1 = {
            [a]: function (arg) {
                console.log(arg)
            }
        }
        obj1[a](123);  //123
        // Symbol作为属性名时,该属性是公有属性,不是私有属性,
        
        // 使用场景:
        // 1、定义一组常量,保证常量的值都不相等.示例1:
        const log = {};
        log.levels = {
            DEBUG: Symbol('debug'),
            INFO: Symbol('info'),
            WARN: Symbol('warn')
        }
        console.log(log.levels.DEBUG, 'debug messagee'); //Symbol(debug) "debug messagee"
        console.log(log.levels.INFO, 'info messagee'); //Symbol(info) "info messagee"
        // 示例2:
        const COLOR_RED = Symbol();
        const COLOR_GREEN = Symbol();
        function getComplement(color) {
            switch (color) {
                case COLOR_RED:
                    return COLOR_RED;
                case COLOR_GREEN:
                    return COLOR_GREEN;
                default:
                    throw new ERROR('undefined color')
            }
        }
        // 常量使用symbol值最大好处,就是其他任何值都不可能有相同的值,因此可以保证上面的switch语句会按设计的方式工作。

        //2、作为对象的key属性,防止对象属性被重写,示例:
        let name = Symbol();
        {
            plugin = {};
            plugin[name] = 'plugin';
            console.log(plugin[name]); //plugin
        }
        {
            let name = Symbol();
            plugin[name] = 'user';
            console.log(plugin[name]);//user

        }
        console.log(plugin); //{Symbol(): "plugin", Symbol(): "user"}
        console.log(plugin[name]); //plugin

        // 当使用了Symbol作为对象的属性key后,在对该对象进行key的枚举时,会有什么不同?在实际应用中,我们经常会需要使用Object.keys()或者for...in来枚举对象的属性名,那在这方面,Symbol类型的key表现的会有什么不同之处呢?来看以下示例代码:
        let object1 = {
            [Symbol('name')]: '一斤代码',
            age: 18,
            title: 'enginner'
        }
        Object.keys(object1);//["age", "title"]
        for (let p in object1) {
            console.log(p); //age title
        }
        Object.getOwnPropertyNames(object1);//["age", "title"]
        // 从以上代码的输出,不难看出,Symbol类型的key是不能通过Object.keys()或者for...in来枚举,它未被包含在对象自身的属性名集合(property names)之中。所以,利用该属性,我们可以把一些不需要对外操作和访问的属性使用Symbol来定义。
        // 当使用JSON.stringify(),将对象转换为JSON字符串时,Symbol也被排除在外,即不含Symbol的值。
        console.log(JSON.stringify(object1)); //{"age":18,"title":"enginner"} 
        
        // 那么,怎么获取以Symbol方式定义的对象属性呢?可以使用下列针对Symbol的API:
        // => 使用Object的API:
        Object.getOwnPropertySymbols(object1); //[Symbol(name)]
        // => 使用新增的反射API
        Reflect.ownKeys(object1); //(3) ["age", "title", Symbol(name)]

        // 3、使用Symbol定义类的私有属性/方法
        // 模块化中的使用,在a.js文件中:
        const PASSWORD = Symbol();
        class Login {
            constructor(username, password) {
                this.username = username;
                this[PASSWORD] = password;
            }
            checkPassword(pwd) {
                return this[PASSWORD] === pwd
            }
        }
        export default Login;

        // b.js文件:
        import Login from './a.js';
        const login = new Login('admin', '123455');
        login.checkPassword('123456');
        login.PASSWORD // oh!no! 
        login[PASSWORD];// oh!no!
        login['PASSWORD']// oh!no!

        // 由于Symbol常量被定义在a.js模块中,在b。js中拿不到,也不能创建一个一模一样的(是唯一的),所以这个PASSWORD是限制在a.js中。所以使用它来定义的类属性是没有办法被模块外访问到的,达到了一个私有化的效果。
        // 注册和获取全局Symbol
        //通常情况下,在浏览器窗口(window)中,使用Symbol()函数来定义和Symbol实例就够了,但,如果应用设计到多个window(如使用iframe),并需要这些window中创建的Symbol是同一个,就不能使用Symbol()函数了。要使用另一个API:就是Symbol.for()
        //可以注册或获取一个window间全局的Symbol实例
        let gs1 = Symbol.for('global_symbol_1');  //注册一个全局Symbol
        let gs2 = Symbol.for('global_symbol_1');
        //获取全局Symbol
        console.log(gs1 === gs2); //true 

</script>      

参考:https://www.jianshu.com/p/f40a77bbd74e

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值