美文网首页
symbol 的理解和使用

symbol 的理解和使用

作者: 达文西_Huong | 来源:发表于2020-06-17 10:55 被阅读0次

理解和使用ES6中的 Symbol

原文:https://www.jianshu.com/p/f40a77bbd74e


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间也是唯一的了。

以上

相关文章

  • symbol 的理解和使用

    理解和使用ES6中的 Symbol 原文:https://www.jianshu.com/p/f40a77bbd7...

  • 深入理解 Symbol

    深入理解 Symbol深入理解 Symbol

  • Symbol

    理解和使用ES6中的 Symbol 原文:https://www.jianshu.com/p/f40a77bbd7...

  • 理解和使用ES6中的Symbol

    ES6中引入了一种新的基础数据类型:Symbol,不过很多开发者可能都不怎么了解它,或者觉得在实际的开发工作中并没...

  • 理解和使用ES6中的Symbol

    ES6中引入了一种新的基础数据类型:Symbol,不过很多开发者可能都不怎么了解它,或者觉得在实际的开发工作中并没...

  • ruby中symbol 和 string

    1. 了解symbol symbol是什么符号(symbol)和字符串很相似,符号也是对象,一般作为名称标签来使用...

  • Symbol (es6)

    1.为什么要使用Symbol 2.Symbol的基本使用 3.Symbol值作为key 4.遍历对象中的Symbo...

  • 【TS】使用Symbol报错

    使用webstorm写typescript时,Symbol会报错:cannot find name 'Symbol...

  • vue cli3使用svg-sprite-loader

    iconfont symbol对比svg-sprite-loader iconfont symbol在SVG使用上...

  • 第二十七节: ES6 Symbol 与Set,Map

    1.数据类型Symbol 1.1 理解Symbol 1.1.1为什么用Symbol ES5里面对象的属性名都是字...

网友评论

      本文标题:symbol 的理解和使用

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