专栏首页OECOMES6中的Symbol有什么卵用

ES6中的Symbol有什么卵用

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

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

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

// 没有参数的情况
var s1 = Symbol();
var s2 = Symbol();
s1 === s2 // false
// 有参数的情况
var s1 = Symbol("foo");
var s2 = Symbol("foo");
s1 === s2 // false

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

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

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

作为属性名

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来赋值可不可以,如果你用了,那么你就应该去补补基础了,因为点运算符后面的值必须是字符串,用点运算符访问会报错。

下面来看一下这个例子

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属性名我们来看一下下面这个图

全局 Symbol 注册表

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

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

var s1 = Symbol.for('oecom');
var s2 = Symbol.for('oecom');
s1===s2 //返回true
console.log(s1); //Symbol(oecom)

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

var s1 = Symbol.for("oecom");
Symbol.keyFor(s1) // "oecom"

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

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

用途

1.创建枚举类型

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

const directions = {
    UP   : Symbol( 'UP' ),
    DOWN : Symbol( 'DOWN' ),
    LEFT : Symbol( 'LEFT' ),
    RIGHT: Symbol( 'RIGHT' )
};

2.避免名称冲突

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

3.设置半私有属性

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

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 通过css设置滚动条样式

    在移动端通常情况下滚动条是不显示出来,这样会让一些不明就里的人不知道是否可以滑动查看更多的信息,通过css可以来设置滚动条的样式,并且让它一直显示出来。

    无邪Z
  • js校验ip、子网掩码、网关的合法性

    IP的格式是xxx.xxx.xxx.xxx每个段的最大值为255,故可以采用正则表达式的方式来进行校验

    无邪Z
  • 显示3D文字且左右摆动效果

    图片的进出特效前面介绍过不少,但是没有介绍过文字的特效,今天我来给大家介绍一种特效。相信大家在大街上都看到过店铺的招牌,有的招牌的文字为3D效果,并且后面还能看...

    无邪Z
  • es6 Symbol

    1.Symbol 值通过Symbol 函数生成,凡是属性名属于Symbol 类型,就是   独一无二的,可以保证不会与其他属性名冲突。       // 没有参...

    用户1197315
  • 理解和使用ES6中的Symbol

    ES6中引入了一种新的基础数据类型:Symbol,不过很多开发者可能都不怎么了解它,或者觉得在实际的开发工作中并没有什么场景应用到它,那么今天我们来讲讲这个数据...

    一斤代码
  • ES6之symbol

    为什么需要使用Symbol 考虑到以下场景: // a library var L = (function() { var prop1 = 'prop1...

    糊糊糊糊糊了
  • Javascript Symbol 解惑 什么是Symbol创建Symbol如何使用Symbol

    Symbol是ES6中新引入的一种基本数据类型,在此之前Javascript中已有几种基本数据类型:

    MudOnTire
  • 重温 ES6 Symbol

    1.Symbol 通过工厂函数创建,不能以 new 的方式创建,所以使用 instanceof 运算符返回的结果为 false

    阿宝哥
  • 前端测试题: 关于Symbol,错误的说法是?

    Symbol是由ES6规范引入的一项新特性,它的功能类似于一种标识唯一性的ID。通常情况下,我们可以通过调用Symbol()函数来创建一个Symbol实例.

    舒克

扫码关注云+社区

领取腾讯云代金券