Symbol

ES6中引入了一种新的基础数据类型symbol,但是一直以来都没什么机会了解,今天看了一篇文章里面偶然提到,然后发现自己不懂,于是就去百度了一波。然后就发现了这么一篇精品。为了加深自己的理解,于是转载过来。同时也方便自己以后复习用。

如果转载的不好,还请移步到原文。

这是一种新的基础数据类型 (primitive type)

symbol 是由ES6 规范引入的一项新特性,它的功能类似于一种唯一标识的id。我们一般直接调用symbol()来创建一个symbol实例。

    let s1 = Symbol()

 或者你也可以在调用Symbol()的时候,传入一端字符串。该字符串相当于Symbol实例的描述

    let s2 = Symbol('another symbol')

 由于symbol是一种基础的数据类型,所以当我们用typeof 查看的时候 返回的是 symbol

    typeof s1 // 'symbol'

 同时symbol 的实例时唯一的,所以,当你比较两个symbol的时候,总会返回false

    let s1 = Symbol()
    let s2 = Symbol('another symbol')
    let s3 = Symbol('another symbol')

    s1 === s2 // false
    s2 === s3 // false
 应用场景1 -- 使用symbol来作为对象属性名(key)

 在以前,我们定义一个对象的属性的时候

    let obj {
        abc:123,
        "hello":"world"
    }

    obj['abc']   // 123
    obj['hello'] // world

 而现在,使用symbol可以同样定义对象的属性

    const PROP_NAME = Symbol()
    const PROP_AGE  = Symbol()

    let obj = {
        [PROP_NAME]:"huong"
    }
    obj[PROP_AGE] = 18

    obj[PROP_NAME] // "huong"
    obj[PROP_AGE]  // 18

 关于对象的枚举。如果使用了Symbol定义的属性,在使用传统的for..inObject.keys()是不能   枚举到的。

    let obj = {
        [Symbol('name')]:"huong",
        age: 18,
        title:'Engineer'
    }
    Object.keys(obj) // ['age','title']

    for(let p in obj){
        console.log(p)  // age title
    }

    Object.getOwnPropertyNames(obj)  // ['age','title']

 由上代码可知,Symbol类型的key是不能通过传统方式去枚举出来的。因为它并未被包含在自身   的属性名合集中(property names)。所以利用该特性,我们可以把一些不需要对外操作和访问的   属  性使用Symbol来定义。同样,使用JSON.stringify()将对象转成字符串时候,Symbol属性也   会被排除在输出内容之外

    JSON.stringify(obj)  // {"age":18 , "title":"Engineer" }

 我们可以利用这一特点来更好的设计我们的数据对象,让"对内操作" 和 "对外选择性输出" 变得更   加优雅

 然而这样的话,我们就没办法获取以Symbol方式定义的对象属性了么。也不是,还是有一些专门   针对Symbol的API滴

    // 使用Object的API
    Object.getOwnPropertySymbols(obj)  // [Symbol(name)]

    // 使用新增的反射API
    Reflect.ownKeys(obj)  // [Symbol(name), 'age', 'tile' ]
 应用场景2 使用Symbol来替代常量

 先来看看下面的代码

    const TYPE_AUDIO = 'AUDIO'
    const TYPE_VIDEO = 'VIDEO'
    const TYPE_IMAGE = 'IMAGE'

    function handleFileResource(resource) {
        switch(resource.type) {
            case TYPE_AUDIO:
                playAudio(resource)
                break
            case TYPE_VIDEO:
                playVideo(resource)
                break
            case TYPE_IMAGE:
                previewImage(resource)
                break
            default:
                throw new Error('Unknown type of resource')
        }
    }

 现在有了Symbol 我们可以改成这样

    const TYPE_AUDIO = Symbol()
    const TYPE_VIDEO = Symbol()
    const TYPE_IMAGE = Symbol()

    function handleFileResource(resource) {
        switch (resource) {
            case TYPE_AUDIO:
                console.log('TYPE_AUDIO')
                break
            case TYPE_VIDEO:
                console.log('TYPE_VIDEO')
                break
            case TYPE_IMAGE:
                console.log('TYPE_IMAGE')
                break
            default:
                throw new Error('Unknown type of resource')
        }
    }

    // 当你想要判断的时候只需要把值传进去
    handleFileResource(TYPE_VIDEO)      // TYPE_AUDIO
 应用场景3 使用Symbol定义类的私有属性/方法

 使用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'

    const login = new Login('admin', '123456')

    login.checkPassword('123456')   // true

    login.PASSWORD      // oh!no!
    login[PASSWORD]     // oh!no!
    login['PASSWORD']   // oh!no!

由于Symbol常量被定义在a.js中,外面的模块是访问不了这个Symbol的。因此可以达成一个私有变量。

注册和获取全局Symbol

通常情况下,我们在一个浏览器窗口中(window),使用Symbol() 函数来定义和Symbol实例就足够了。但是如果你想你想多个window中使用某些Symbol是同一个。那就不能使用Symbol()函数。需要用到另一个API去定义Symbol.for()它可以注册或获取一个window间全局的Symbol实例

    let gs1 = Symbol.for('golbal_symbol_1') // 注册一个全局Symbol
    let gs2 = Symbol.for('global_symbol_1') // 获取全局的Symbol
    
    gs1 === gs2   // true

这样一个Symbol不光在单个window中是唯一的,在多个相关window间也是唯一的了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值