前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ES6中的Symbol有什么卵用

ES6中的Symbol有什么卵用

作者头像
OECOM
发布2020-07-02 11:44:54
2540
发布2020-07-02 11:44:54
举报
文章被收录于专栏:OECOM

在ES6中新增了一中类型,这个类型叫做Symbol,最大的特点号称独一无二,下面我们来说一下这东西怎么用,最后再说一下他用在哪。

首先要注意的一点是,Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,而不是个对象

Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。

代码语言:javascript
复制
// 没有参数的情况
var s1 = Symbol();
var s2 = Symbol();
s1 === s2 // false
// 有参数的情况
var s1 = Symbol("foo");
var s2 = Symbol("foo");
s1 === s2 // false

通过上面的代码我们可以发现这货还真是独一无二,即使两个变量赋予了相同的值,他还是不一样,返回false。有好事者就会提出一个想法就是s1给s2赋值,他想不相等呢?

ES6中的Symbol有什么卵用
ES6中的Symbol有什么卵用

很明显的结果,这俩相等。

作为一个独一无二的类型,他也有自己的脾气,那就是不能和任何类型进行运算,否则就会报错。但是他也有大众化的一点,那就是他可以作为属性名

作为属性名

代码语言:javascript
复制
var mySymbol = Symbol();
// 第一种写法
var a = {};
a[mySymbol] = 'Hello!';
// 第二种写法
var a = { [mySymbol]: 'Hello!'};
// 第三种写法
var a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
// 以上写法都得到同样结果
a[mySymbol] // "Hello!"

如果你想问我用a.mySymbol来赋值可不可以,如果你用了,那么你就应该去补补基础了,因为点运算符后面的值必须是字符串,用点运算符访问会报错。

下面来看一下这个例子

代码语言:javascript
复制
let a = {};
a.name = 'oecom';
let name = Symbol();
a[name] = 'oecom.cn';
console.log(a.name,a[name]);             //oecom,oecom.cn

注意,我上面是用let声明变量,并且声明在了a.name后面,否则会报错的,这个就涉及到了变量提升了。通过这个例子应该就可以明白Symbol在属性名上的应用是什么效果了。

Symbol值作为属性名时,该属性还是公开属性,不是私有属性。这个有点类似于java中的protected属性(protected和private的区别:在类的外部都是不可以访问的,在类内的子类可以继承protected不可以继承private)。但是这里的Symbol在类外部也是可以访问的,只是不会出现在for...in、for...of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()返回。但有一个Object.getOwnPropertySymbols方法,可以获取指定对象的所有Symbol属性名我们来看一下下面这个图

ES6中的Symbol有什么卵用
ES6中的Symbol有什么卵用

全局 Symbol 注册表

ES6 有一个用于创建 Symbol 的全局资源:Symbol 注册表,它为字符串和 Symbol 提供了一对一的关系。注册表使用 Symbol.for( key )返回 Symbol。

Symbol.for机制有点类似于单例模式,首先在全局中搜索有没有以该参数作为名称的Symbol值,如果有,就返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值。和直接的Symbol就点不同了。

代码语言:javascript
复制
var s1 = Symbol.for('oecom');
var s2 = Symbol.for('oecom');
s1===s2 //返回true
console.log(s1); //Symbol(oecom)

Symbol.keyFor方法返回一个已登记的Symbol类型值的key。实质就是检测该Symbol是否已创建

代码语言:javascript
复制
var s1 = Symbol.for("oecom");
Symbol.keyFor(s1) // "oecom"

var s2 = Symbol("oecom");
Symbol.keyFor(s2) // undefined

说了这么多了,可能你还是感觉这东西有啥用啊,平时也用不到啊,那么接下来就说一下他的用途。

用途

1.创建枚举类型

枚举允许你定义具有语义名称和唯一值的常量。假定 Symbol 的值不同,它们能为枚举类型提供最好的值。

代码语言:javascript
复制
const directions = {
    UP   : Symbol( 'UP' ),
    DOWN : Symbol( 'DOWN' ),
    LEFT : Symbol( 'LEFT' ),
    RIGHT: Symbol( 'RIGHT' )
};
2.避免名称冲突

当使用 Symbol 作为变量时,我们不必建立可用标识符的全局注册表,也不必费心思想标识符名字,只需要创建一个 Symbol 就行了。一些外部库的做法也是这样。

3.设置半私有属性

根据for in 和for of循环均不能访问到Symbol,我们可以将其作为一个半私有属性

代码语言:javascript
复制
let Square = (function() {
    const _width = Symbol('width');
    class Square {
        constructor( width0 ) {
            this[_width] = width0;
        }
        getWidth() {
            return this[_width];
        }
    }
    return Square;
} )();

这样做的好处是,他人很难访问到我们对象的私有_width值,而且也能很好地区分,哪些属性是公有的,哪些属性是私有的。但这种方法的缺点也很明显:

  • 通过调用Object.getOwnPropertySymbols,我们可以使用 Symbol 键。
  • 如果要写很多的代码,这会使得开发者的体验不佳,访问私有属性不像 Java 或 TypeScript 那样方便。

如果你要用 Symbol 来表示私有字段,那你需要表明哪些属性不能被公开访问,如若有人试图违背这一规则,理应承担相应的后果。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-12-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 作为属性名
  • 全局 Symbol 注册表
  • 用途
    • 1.创建枚举类型
      • 2.避免名称冲突
        • 3.设置半私有属性
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档