ECMA Script 6_Symbol() 唯一类型值声明函数_Symbol 数据类型

Symbol 数据类型

  • let s = Symbol();
    
    typeof s;    // "symbol"

是 ES6 继 Number,String,Boolean,Undefined,Null 之后引入的新数据类型

对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型

Symbol 函数的参数只是表示对当前 Symbol 值的描述

  • let s1 = Symbol('foo');
    let s2 = Symbol('bar');
    
    s1     // Symbol(foo)
    s2     // Symbol(bar)
    
    s1.toString();     // "Symbol(foo)"
    s2.toString();     // "Symbol(bar)"

凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突

背景:

ES5 的对象属性名都是字符串,这容易造成属性名的冲突

如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。

  • 原始数据类型 Symbol

表示独一无二的值。

它是 JavaScript 语言的第七种数据类型

Symbol 值可以显式转为字符串

Symbol 值可以显式转为布尔值

  • Symbol 值不能与其他类型的值进行运算,会报错
  • 即使 Symbol 函数参数相同,但是它们是不相等的。
  • Symbol 值 作为对象的属性时,只能用 [ ] 访问进行读写

在对象的内部,使用 Symbol 值定义属性时,Symbol 值必须放在方括号之中

  • let s = Symbol();
    
    let obj = {
        [s]: function (arg) { ... }
    };
    
    obj[s](123);
  • 常量使用 Symbol 值最大的好处,就是其他任何值都不可能有相同的值了,因此可以保证上面的switch语句会按设计的方式工作
  • const COLOR_RED    = Symbol();
    const COLOR_GREEN  = Symbol();
    
    function getComplement(color) {
        switch (color) {
            case COLOR_RED:
                return COLOR_N:
                return COLOR_GREEN;
            case COLOR_GREERED;
            default:
                throw new Error('Undefined color');
        };
    };
  • 消除魔术字符串的方法,就是把它写成一个变量
  • const shapeType = {
        triangle: Symbol(),
    };
    
    function getArea(shape, options) {
        let area = 0;
        switch (shape) {
            case shapeType.triangle:
                area = .5 * options.width * options.height;
                break;
        };
        return area;
    };
    
    getArea(shapeType.triangle, { width: 100, height: 100 });
  • Symbol 作为属性时,非私有属性,遍历法
  • Symbol 作为属性名,该属性不会出现在for...infor...of循环中,也不会被Object.keys()Object.getOwnPropertyNames()JSON.stringify()返回
  • 但是,它也不是私有属性,有一个 Object.getOwnPropertySymbols() 获取指定对象的所有 Symbol 属性名
  • 重新使用同一个 Symbol 值,Symbol.for('aName')

接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。

  • 如果有,就返回这个 Symbol 值
  • 否则就新建并返回一个以该字符串为名称的 Symbol 值
  • let s1 = Symbol.for('foo');    // 登记在全局环境中供搜索
    let s2 = Symbol.for('foo');    // 登记在全局环境中供搜索
    
    s1 === s2 // true

Symbol.for()Symbol()这两种写法,都会生成新的 Symbol。

它们的区别是:

前者会被登记在全局环境中供搜索,后者不会。

Symbol.for()不会每次调用就返回一个新的 Symbol 类型的值,而是会先检查给定的key是否已经存在,如果不存在才会新建一个值。

比如,如果你调用Symbol.for("cat")30 次,每次都会返回同一个 Symbol 值,

但是调用Symbol("cat")30 次,会返回 30 个不同的 Symbol 值

  • Symbol.keyFor() 返回一个已登记的 Symbol 类型值的 key,即 Symbol.for() 生成的 Symbol 值
  • 注意: 为 Symbol 值登记的名字,是全局环境的,可以在不同的 iframe 或 service worker 中取到同一个值
  •  
    let obj = {
        [Symbol('my_key')]: 1,
        enum: 2,
        nonEnum: 3
    };
    
    Reflect.ownKeys(obj);    //  ["enum", "nonEnum", Symbol(my_key)]

 

posted @ 2018-12-15 11:53  耶梦加德  阅读(418)  评论(0编辑  收藏  举报