博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES6精华:Symbol
阅读量:5941 次
发布时间:2019-06-19

本文共 4086 字,大约阅读时间需要 13 分钟。

它是JS的第七种类型,属于基本类型。

它表示一个独一无二的值,行为类似字符串。
它是直接通过Symbol函数生成的,可以传入字符作为该值的描述。

const symbol1 = Symbol('unique');const symbol2 = Symbol('unique');console.log(symbol1 === symbol2); // false

应用举例

替代用于识别的字符串常量

--- 之前const MY_ONE = 'unique-one';if (MY_ONE === 'unique-one') { ... }虽然定义了保存值的常量,但直接使用值或再定义相同值的变量也是没有问题的。--- 现在const MY_ONE = Symbol('one');if (MY_ONE === MY_ONE) { ... }如果想使用该常量,必须直接使用该常量或其一个副本,因为 Symbol('one') 是绝对唯一的。

作为间接实现私有属性和方法的途径

只有使用 private_a / private_b 变量所指向的值才能访问到相应的属性值。const private_a = Symbol('private_a');const private_b = Symbol('private_b');function Class() {  this[private_a] = 'private_a';}Class.prototype[private_b] = function() {  console.log('private_b');}

作为自定义接口或不同数据集合统一接口的名称

示例:为 Array 增加并集的计算方法,使用此方法可以避免未来可能的命名冲突。const CusArrayAPIMap = {  union: Symbol('cus-array-api-union')};Array[CusArrayAPIMap.union] = function() {  return [...new Set([...arguments].reduce((a, b) => a.concat(b), []))];};Array[CusArrayAPIMap.union]([1, 3], [2, 3]); // [1, 3, 2]

转化规则

symbol值不可转化成数字(作为一个唯一值无对应的数值)。

symbol值可以转化成布尔值(不管怎样,它是有值的,所以恒为true)。
symbol值不可被隐式转化成字符串,但是可以显示转化(隐式即计算,拿一个唯一值计算没意义,但直接打印成字符串查看是可以的)。

Symbol() + 2; // 报错Number(Symbol()); // 报错Boolean(Symbol()); // 恒为 trueif (Symbol()) { ... } // 恒执行Symbol() + '-'; // 报错String(Symbol()); // "Symbol()"Symbol().toString(); // "Symbol()"

Symbol.for()

Symbol.for(key)Symbol()一样,用来返回一个唯一值。

不过其传入的key与生成的值会形成映射存储在全局的symbol注册表中。
即是说,Symbol.for(key)是先根据key在注册表中寻找,有直接返回,没有创建并返回。
也即是说,在相同的全局空间中(包括不同的iframeservice worker)传入相同的key取出来的是同一值。

Symbol('one') === Symbol('one'); // falseSymbol('one') === Symbol.for('one'); // falseSymbol.for('one') === Symbol.for('one'); // trueSymbol.for('one') === Symbol.for('two'); // false

相配套的还有方法Symbol.keyFor()

它会根据传入的Symbol值,去注册表中查找并返回对应的key

let o = Symbol.for('one');Symbol.keyFor(o); // 'one'Symbol.keyFor(Symbol('two')); // undefinedSymbol.keyFor(Symbol.for('two')); // 'two'

内置的 Symbol 值

ES6规定了11个内置接口的统一名称。

可以将这些接口部署到自定义对象或构造函数上,同步原生操作。

Symbol.toStringTag

指向一个字符串,表示该对象的类型标签。
通俗的说,就是使用Object.prototype.toString.call(target)获取到的[object Name]中的Name

let obj = {  [Symbol.toStringTag]: 'MyTag'};console.log( Object.prototype.toString.call(target) ); // '[object MyTag]'

Symbol.toPrimitive

指向一个方法,当该对象被转化成NumberString型时会被调用。
该方法会接受一个字符串参数,表示当前场合需要转化成什么类型,一共有三种模式:numberstringdefault(转化成两者都行)。

let obj = {  [Symbol.toPrimitive](type) {    switch(type) {      case 'number':        return 3;        break;      case 'string':        return 's';        break;      case 'default':        return 'd';        break;    }  }};console.log( Number(obj) ); // 3console.log( String(obj) ); // 's'console.log( obj + 1 );  // 'd1'

Symbol.hasInstance

指向一个方法,是instanceof命令实际调用的方法。

[] instanceof Array; // true实际是执行下面代码。Array[Symbol.hasInstance]([]); // true可自行为自定义对象添加此接口。let OBJ = {  [Symbol.hasInstance](arr) {    return arr.length === 2 ? true : false;  }};[1] instanceof OBJ; // false[1, 2] instanceof OBJ; // true

Symbol.iterator

指向对象的默认遍历器方法(关于遍历器可看Iterator章节)。
数组默认的遍历器方法为:Array.prototype[Symbol.iterator]

Symbol.species

指向一个方法,该方法返回一个构造函数。当实例需要调用自身的构造函数时方法会被调用。
有些类库是在基类的基础上修改的,当子类使用继承的方法时,作者希望返回基类的实例,而不是子类的实例。

class MyArray extends Array {  static get [Symbol.species]() { return Array }}let a = new MyArray(1, 2, 3);let b = a.map(x => x);console.log(b instanceof Array); // trueconsole.log(b instanceof MyArray); // falseb 是 a 的衍生对象,或称派生对象。如果没有 [Symbol.species] ,b 原型链中第一个对象应为 MyArray 原型。但现在第一个对象为 Array 的原型,即 b 直接为 Array 的实例。

Symbol.split, Symbol.match, Symbol.search, Symbol.replace

四者都是针对字符串与正则(对象)的关系,指向一个方法,具有相同行为。

let reg = /m/g;let str = 'Hi, I\'m programmer monkey';str.replace(reg, 'M');实际是执行下面的代码。reg[Symbol.replace](str, 'M');

Symbol.isConcatSpreadable

指向一个布尔值,表示该对象用于Array.prototype.concat()时是否可以展开。
默认没有该属性,即为undefined,等同于true。设置为false则不展开。

let arr = [1, 2];arr[Symbol.isConcatSpreadable] = false;[3].concat(arr); // [3, [1, 2]]

Symbol.unscopables

指向一个对象,该对象指定了使用with关键字时,哪些属性会被with环境排除。

let obj = {  id: '123',  name: 'limo',  [Symbol.unscopables]: {    id: true  }};let id = 'id';let name = 'name';with (obj) {  console.log(id); // 'id'  console.log(name); // 'limo'}

转载地址:http://xcqtx.baihongyu.com/

你可能感兴趣的文章
开源 java CMS - FreeCMS2.6 静态化管理
查看>>
开源 java CMS - FreeCMS2.8 数据对象 applyopen
查看>>
UI控件
查看>>
自己整合优化的一个Android框架
查看>>
Android内核剖析 目录
查看>>
jsf如何通过按钮切换在同一个页面上的非公共部分显示不同的内容
查看>>
/etc/fstab 文件解释
查看>>
如何用函数表示数(四)数的彻底消失
查看>>
windows 7下同时安装visual studio 2012和2010
查看>>
android--------Socket的简单了解
查看>>
安卓错误Emulator: error: x86 emulation currently......
查看>>
Asynchronous CDI Events
查看>>
mynginx.conf
查看>>
Oracle——20数据库恢复与备份
查看>>
鼠标坏了你别扔,可以修的
查看>>
CentOS 中使用yum时常见的一种提示信息
查看>>
记一次ssh登录异常
查看>>
01-利用思维导图梳理JavaSE-Java语言基础
查看>>
RocketMQ几种搭建模式说明
查看>>
程序分析思路
查看>>