JavaScript —— Symbol数据类型之不延伸

JavaScript —— Symbol数据类型之不延伸

导语:Symbol是一种基本数据类型,每个从Symbol()返回的值都是唯一的。一个symbol的值能作为对象属性的标识符,这是该数据类型仅有的目的。 ---- 《摘自MDN》

敲黑板:唯一的、标识符

这句话值得我们细细咀嚼,我们由上面这句话来展开思考。说到唯一性,我们可以联想到的数据类型有什么?

  1. const常量 —— 《传送地址》
  2. TypeScript枚举enum —— 《传送地址》
  3. TypeScript Symbol

下面我们就这三种数据类型展开对比:

一、叭叭JavaScript的Symbol

属于是ES6新增的数据类型,在ES6之前,只有string,number,boolean,null,undefinedObject六种数据类型,Symbol属于新增的基本数据类型。后面还新增了BigInt数据类型等。

  1. 创建Symbol,简单举个例子:
let a = Symbol('a'); // 也可以直接 Symbol()

这样就创建好了一个Symbol数据类型,任何其他的数据类型都与之不相等,例如:

let b = Symbol('a');
console.log(a == b) // false

我们在使用console.log()去输出Symbol的时候,会隐式调用SymboltoString()方法,例如:

console.log(a); // Symbol(a)

反之,我们使用typeof去控台输出,返回的是数据类型,例如:

console.log(typeof a); // symbol
  1. 创建Symbol的时候,可以添加一个可选参数作为描述,这样使Symbol更具有语义性,例如:
let name = Symbol('name');
console.log(name); // Symbol(name)
  1. 获取Symbol的标识符,使用Symbol.keyFor()方法,例如:
let c = Symbol('d');
console.log(Symbol.keyFor(c)); // 输出 d

备注:如果不添加标识符参数创建变量之后,该方法输出为undefined,例如:

let e = Symbol();
console.log(Symbol.keyFor(e)); // 输出 undefined
  1. Symbol的共享,虽然不知道有啥用,例如:
let a = Symbol.for('a');
let b = Symbol.for('a');
console.log(a == b); // true

二、TypeScript的Symbol

跟JavaScript的一样,因为TypeScript只是一个JavaScript超级,本质还是会将TS代码通过TSLint(虽然已经废用),转换成JavaScript代码,你可以理解为同Babel差不多,因此不再赘述。

三、Symbol的作用及延伸

  1. 唯一的值,例如:
let orderStatus = {
  OPEN: Symbol('已下单'),
  ON: Symbol('配送中'),
  COMPLETED: Symbol('订单完成'),
  CANCELED: Symbol('取消订单')
}

看起来似乎很美好对吧?每个状态都有自己唯一的值,类似于enum。只是,,

通常,我们都晓得,获取到的后端数据,用于判断状态和入库的数据一般都是0,1,2…

为什么?

  • 第一,从字节编码层面考虑,可以避免编码格式问题,你的’男’或者’女’如果编码格式有误则乱码入库,后患无穷;
  • 第二,从存储空间层面考虑,UTF8的一个汉字占三个字节,而一个数字只有一个字节…且更加方便开发者维护;
  • 第三,从数据库检索层面考虑,字节越少,耗时约短,查询的效率随之更高。

这时候我问你,你难道还希望后端返回Symbol数据类型给你吗?

那这时候有朋友就说:啊我不管,我就要这种数据类型,看起来多酷哇!

如果是,那我希望你不会被施与爱的关怀…万一咱们后端同事同意使用这种数据类型了,那我希望你们以后不会被维护的人隔空给你们来一句爱的问候~(dog狗头)

  1. 唯一的key,例如:
let status = Symbol('status');

let ordering = {
    [status]: 1,
    description: '杨国福麻辣烫加麻加辣!'
};

console.log(ordering); // {description: '杨国福麻辣烫加麻加辣!', Symbol(status): 1}

使用Object.keys()获取对象的所有可枚举属性,例如:

console.log(Object.keys(ordering)); // ["description"]

使用Object.getOwnPropertyNames()获取所有属性,无论是否可以枚举,例如:

console.log(Object.getOwnPropertyNames(ordering)); // ["description"]

那么要获取对象中的Symbol属性,需要使用ES6新增的Object.getOwnPropertySymbols()方法,例如:

console.log(Object.getOwnPropertySymbols(ordering)); // [Symbol(ordering)]
  1. 众所周知的Symbols

除了用户定义的Symbols,还有一些已经众所周知的内置Symbols。 内置Symbols用来表示语言内部的行为。

  • Symbol.hasInstance 方法,会被instanceof运算符调用。构造器对象用来识别一个对象是否是其实例。
  • Symbol.isConcatSpreadable 布尔值,表示当在一个对象上调用Array.prototype.concat时,这个对象的数组元素是否可展开。
  • Symbol.iterator 方法,被for-of语句调用。返回对象的默认迭代器。
  • Symbol.match 方法,被String.prototype.match调用。正则表达式用来匹配字符串。
  • Symbol.replace 方法,被String.prototype.replace调用。正则表达式用来替换字符串中匹配的子串。
  • Symbol.search 方法,被String.prototype.search调用。正则表达式返回被匹配部分在字符串中的索引。
  • Symbol.species 函数值,为一个构造函数。用来创建派生对象。
  • Symbol.split 方法,被String.prototype.split调用。正则表达式来用分割字符串。
  • Symbol.toPrimitive 方法,被ToPrimitive抽象操作调用。把对象转换为相应的原始值。
  • Symbol.toStringTag 方法,被内置方法Object.prototype.toString调用。返回创建对象时默认的字符串描述。
  • Symbol.unscopables 对象,它自己拥有的属性会被with作用域排除在外。

四、总结

通过开头的导语、通篇的分析对比特性,我们知道:Symbol它的目的仅仅是为对象属性添加独特一个标识符而已。而我们之前分析的const常量和TypeScript enum枚举,它俩都有添加标识符的能力,但总的就一句话,哪种数据类型更加契合业务环境,你就用哪种。如果在复杂性较高的大型项目里,针对对象属性,想要规避出现相同的数据造成的变量混乱,Symbol永远是你的最优选择;想要区分不同业务场景下使用的某些变量,从而达到规避魔数、整洁代码的目的,enum是不二之选;相反,const常量往往都是作为一个固定的数据出现,例如公数、当前日期时间等等…

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值