ES6中的Symbol


title: ES6中的Symbol

  • Symbol函数前不能使用new命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。

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

  • Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。

  • Symbol值不能与其他类型的值进行运算,会报错。

  • Symbol值也可以转为布尔值,但是不能转为数值。

  • Symbol值一般用作属性名,以防止某个键被覆盖或改写。

    • let mySymbol = Symbol();
      
      // 第一种写法
      let a = {};
      a[mySymbol] = 'Hello!';
      
      // 第二种写法
      let a = {
        [mySymbol]: 'Hello!'
      };
      
      // 第三种写法
      let a = {};
      Object.defineProperty(a, mySymbol, { value: 'Hello!' });
      
      // 以上写法都得到同样结果
      a[mySymbol] // "Hello!"
      
    • 但是Symbol值作为对象的属性名时不能用点运算符:

      const mySymbol = Symbol();
      const a = {};
      
      a.mySymbol = 'Hello!';
      a[mySymbol] // undefined
      a['mySymbol'] // "Hello!"
      
  • 在对象内部使用Symbol值定义属性时,Symbol值必须放在方括号中

    • let s = Symbol();
      
      let obj = {
        [s]: function (arg) { ... }	// 或是对象增强写法: [s](arg) { ... }
      };
      
      obj[s](123);
      

一. 属性名的遍历

作为属性名的Symbol值和其他字符串类型的键不同,无法通过for...infor...of循环中,也不会被Object.keys()Object.getOwnPropertyNames()JSON.stringify()返回。

它通过Object.getOwnPropertySymbols方法返回指定对象的所有Symbol属性名(返回一个数组)

通过此方法可以为对象定义一些非私有的、但又希望只用于内部的方法

let size = Symbol('size');

class Collection {
  constructor() {
    this[size] = 0;
  }

  add(item) {
    this[this[size]] = item;
    this[size]++;
  }

  static sizeOf(instance) {
    return instance[size];
  }
}

let x = new Collection();
Collection.sizeOf(x) // 0

x.add('foo');
Collection.sizeOf(x) // 1

Object.keys(x) // ['0']
Object.getOwnPropertyNames(x) // ['0']
Object.getOwnPropertySymbols(x) // [Symbol(size)]

另一个新的 API,Reflect.ownKeys方法可以返回所有类型的键名,包括常规键名和 Symbol 键名

二. 模块的Singleton模式

Singleton模式指的是调用一个类,任何时候返回的都是同一个实例。

对于node来讲,模块文件可以看作是一个类,为了保证每次执行此模块文件返回的都是同一个实例,我们常把实例放到顶层对象global

// mod.js
function A() {
  this.foo = 'hello';
}

if (!global._foo) {
  global._foo = new A();
}

module.exports = global._foo;

然后加载上边的mod.js

const a = require('./mod.js');
console.log(a.foo);

但问题是我们必须令引用mod.js的诸多文件既可以使用,又无法修改

为防止此情况的发生,我们可以使用Symbol

// mod.js
const FOO_KEY = Symbol('foo');

function A() {
  this.foo = 'hello';
}

if (!global[FOO_KEY]) {
  global[FOO_KEY] = new A();
}

module.exports = global[FOO_KEY];

若键名使用Symbol方法生成,那么外部将无法引用这个值,自然也无法改写。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值