博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入理解ES6之《Symbol》
阅读量:5736 次
发布时间:2019-06-18

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

创建Symbol及辨别方法

Symbol是原始值,因此调用new Symbol会导致程序抛出错误

let firstName = Symbol()let person = {}person[firstName] = "angela"console.log(person[firstName])

使用typeof来辨别其类型

let symbol=Symbol('this is test description')console.log(typeof symbol)//symbol

Symbol可用于计算对象字面量属性名、Object.defineProperty、Object.defineProperties

如果想创建一个共享的Symbol,可使用Symbol.for方法

let uid = Symbol.for('uid')let object = {  [uid]: '12345'}console.log(object[uid])//12345console.log(uid)//Symbol(uid)let uid2 = Symbol.for('uid')console.log(uid === uid2)//trueconsole.log(object[uid2])//12345console.log(uid2)//Symbol(uid)

Symbol.keyFor方法在Symbol全局注册表中检索与Symbol有关的键

let uid = Symbol.for('uid')console.log(Symbol.keyFor(uid))//uidlet uid2 = Symbol.for('uid')console.log(Symbol.keyFor(uid2))//uidlet uid3=Symbol('uid')console.log(Symbol.keyFor(uid3))//undefined

Symbol全局注册表是一个类似全局作用域的共享环境,也就是说你不能假设目前环境中存在哪些键

Symbol与类型强制转换

不能将Symbol强制转换成数字类型,Symbol也不可以被转换成字符串

let uid = Symbol.for('uid')let desc = uid + ""//报错 Uncaught TypeError: Cannot convert a Symbol value to a string
let uid = Symbol.for('uid')let desc = uid / 1//报错  Uncaught TypeError: Cannot convert a Symbol value to a number

但是却可以像下面这样使用

let uid = Symbol.for('uid')let desc = String(uid)console.log(desc)//Symbol(uid)

Symbol属性检索

Object.getOwnPropertySymbols

let uid = Symbol.for('uid')let object = {  [uid]: '12345'}let symbols=Object.getOwnPropertySymbols(object)

Symbol.hasInstance

Symbol.hasInstance只接受一个参数,即要检查的值

每个函数都有Symbol.hasInstance方法,用于确定对象是否为函数实例,该方法在Function.prototype中定义,该方法被定义不为可写、不可配置、不可枚举

let obj = []//obj instanceof Array //下面一句代码与此句功能等价Array[Symbol.hasInstance](obj)//true

我们可以通过Object.defineProperty方法改写一个不可写属性

所以其实可以重写所有内建函数(如Date和Error)默认的Symbol.hasInstance属性

function SpecialNumber() { }Object.defineProperty(SpecialNumber, Symbol.hasInstance, {  value: function (v) {    return (v instanceof Number) && (v >= 1 && v <= 100)  }})var two = new Number(2),  zero = new Number(0);console.log(two instanceof SpecialNumber)//trueconsole.log(zero instanceof SpecialNumber)//false

Symbol.isConcatSpreadable

Symbol.isConcatSpreadable属性值为true表明属性值应当作为独立元素添加到数组中

let c1 = ['red', 'green'],  c2 = c1.concat(['blue', 'black'], 'yellow')console.log(c2)//["red", "green", "blue", "black", "yellow"]

为什么上面一段代码结果是["red", "green", "blue", "black", "yellow"]而不是["red", "green", ["blue", "black"], "yellow"]?

图片描述
如果把上面的代码稍微改一下,结果就完全不一样了

let collection = {  0: 'hello',  1: 'world',  2: 'demo',  3: 'test',  [Symbol.isConcatSpreadable]: true,  length: 4}let msg = ['Hi'].concat(collection)console.log(msg)//["Hi", "hello", "world", "demo", "test"]

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

let hasLenOf10 = {  [Symbol.match](v) {    return v.length === 10 ? [v.substring(0, 10)] : null  },  [Symbol.replace](v, replacement) {    return v.length === 10 ? replacement + v.substring(10) : v;  },  [Symbol.search](v) {    return v.length === 10 ? 0 : -1  },  [Symbol.split](v) {    return v.length === 10 ? ["", ""] : [v]  }}let msg1 = 'Hello world',  msg2 = 'Hello John';console.log(msg1.match(hasLenOf10))//nullconsole.log(msg2.match(hasLenOf10))//[Hello John]console.log(msg1.replace(hasLenOf10))//Hello worldconsole.log(msg2.replace(hasLenOf10))//undefinedconsole.log(msg1.search(hasLenOf10))//-1console.log(msg2.search(hasLenOf10))//0console.log(msg1.split(hasLenOf10))//["Hello world"]console.log(msg2.split(hasLenOf10))//["",""]

Symbol.toPrimitive

在执行特定操作时,经常会尝试将对象转换到相应的原始值

Symbol.toPrimitive被定义在每一个标准类型的原型上,并且规定了当对象被转换为原始值时应该执行的操作
每当执行类型转换总会调用Symbol.toPrimitive方法并传入一个值作为参数,这个值在规范中被称作类型提示hint,类型提示参数只有三种选择number、string、default

function Temperature(degree) {  this.degree = degree}Temperature.prototype[Symbol.toPrimitive] = function (hint) {  switch (hint) {    case "string":      return this.degree + '\u00b0';    case "number":      return this.degree;    case "default":      return this.degree + " degrees"  }}var freezing = new Temperature(32)console.log(freezing + "!")//32 degrees!console.log(freezing / 2)//16console.log(String(freezing))//32°

Symbol.toStringTag

以前判断一个对象的类型一般都是这样

function isArray(value) {  return Object.prototype.toString.call(value) === "[object Array]"}

ES6中我们可以自定义对象字符串标签

function Person(name) {  this.name = name}Person.prototype[Symbol.toStringTag] = "Person"Person.prototype.toString = function () {  return this.name}var me = new Person('angela')console.log(me.toString())//angelaconsole.log(Object.prototype.toString.call(me))//[object Person]

如果我们不重写toString方法,则me.toString返回的值就是[object Person]

我们可以给Person.prototype[Symbol.toStringTag]赋任意值,当然也可以修改原生对象的字符串标签

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

你可能感兴趣的文章
原生CSS设置网站主题色—CSS变量赋值
查看>>
webpack 4.0 中 clean-webpack-plugin 的使用
查看>>
数据库神器:Navicat Premium
查看>>
WPF
查看>>
Best website for Photogrammetry
查看>>
中文词频统计
查看>>
POJ 2236 Wireless Network (并查集)
查看>>
python分类
查看>>
linux 中常见的压缩和解压缩的命令
查看>>
GitBlit (1)-- 在linux 安装 GitBlit 并运行
查看>>
Windows与Linux之间的文件自动同步
查看>>
topcoder srm 714 div1
查看>>
20160215
查看>>
mxnet导入图像数据
查看>>
程序是如何执行的(一)a=a+1
查看>>
go : 结构
查看>>
【Python第五篇】Python面向对象(初级篇)
查看>>
innobackupex参数之 --throttle 限速这个值设置多少合理 原创
查看>>
18 已知下面的字符串是通过RANDOM随机数变量md5sum|cut-c 1-8截取后的结果
查看>>
BZOJ - 3578: GTY的人类基因组计划2
查看>>