es6 快速入门 系列 —— Symbol
其他章节请看:
Symbol
es6新增的一种原始类型
试图解决的问题
唯一的属性名
给对象新增一个属性,如何保证这个属性名是独一无二的?
更改 instanceof 的运行方式
function People(){
}
let p1 = new People();
console.log(p1 instanceof People) // true
如何让上面例子中的 instanceof 返回false?
解决的方法
唯一的属性名
es6引入 Symbol 来解决对象新增属性名唯一性的问题,可以通过全局的 Sysbol 函数创建一个 Symbol,就像这样:
let key1 = Symbol()
let person = {}
// 给person对象新增了一个唯一的属性名key1
person[key1] = '11'
console.log(person[key1]) // 11
注:现在,对象的属性有两种,字符串类型和 Symbol 类型
Symbol 接受一个可选参数,用于描述即将创建的 Symbol,建议你在每次创建 Symbol 都添加这样一段描述,以便于阅读和调试。就像这样:
let fullName = Symbol('full name')
let person = {}
person[fullName] = 'aaron'
console.log('full name' in person) // false
console.log(person[fullName]) // aaron
console.log(fullName) // Symbol(full name)
Symbol是一种新的原始类型(typeof 是最准确也是你最应首选的检测方式),调用 new Symbol() 会报错。
console.log(typeof Symbol()) // symbol
new Symbol() // 报错。Symbole不是构造函数
对于类型转换,Symbol 使用起来不是很灵活,因为其他类型没有与Symbol逻辑等价的值
let id = Symbol()
id + '' // 报错:不能将Symbol转换为字符串
id + 1 // 报错:不能将Symbol转换为数字
console.log(Boolean(id)) // true: Symbol与非空值类似,等价布尔值为true
更改 instanceof 的运行方式
可以通过 Symbol.hasInstance 来更改 instanceof 的运行方式,就像这样:
function People(){
}
Object.defineProperty(People, Symbol.hasInstance, {
value: function(v){
console.log(v) // People {}
return false
}
})
let p1 = new People();
console.log(p1 instanceof People) // false
es6提供了11个内置的 Symbol 值(Symbol.hasInstance就是其一),用于开放以前javascript常见的内部操作,让开发者拥有更多的权限。
补充
全局共享的 Symbol
上面使用 Symbol() 函数的语法,不会在你的整个代码库中创建一个全局的 Symbol 类型;有时我们希望在不同的代码中共享同一个 Symbol;通常,在很大的代码库或跨文档追踪 Symbol 非常困难而且容易出错,出于这些原因,es6 提供了一个可以随时访问的全局 Symnbol 注册表
创建一个全局的Symbol,要使用 Symbol.for() 方法。它只接受一个参数,也就是即将创建的 Symbol 的标识符,这个参数同样也被用作 Symbol 的描述符,就像这样:
// 首先在全局 Symbol 注册表中搜索键为"id"的Symbol是否存在
// 存在则直接返回
// 不存在则创建,然后注册到全局 Symbol 表中,最后返回
let id = Symbol.for('id')
let id2 = Symbol.for('id')
let obj = {};
obj[id] = '111'
console.log(obj[id2]) // 111
console.log(id) // Symbol(id)
console.log(id === id2) // true
可以使用 Symbol.keyFor() 在全局 Symbol 注册表中检索与 Symbol 有关的键。举个例子:
let id1 = Symbol.for('id')
let id2 = Symbol.for('id')
let id3 = Symbol('id')
console.log(Symbol.keyFor(id1)) // id - 全局注册表中有键 id1
console.log(Symbol.keyFor(id2)) // id
console.log(Symbol.keyFor(id3)) // undefined 全局注册表中没有键 id3
注:全局 Symbol 注册表类似全局作用域,尽量使用命名空间以减少命名冲突,例如 jQuery 的代码可以为所有键添加 "jquery" 前缀,就像 jquery.element
内置的Symbol
Symbol.hasInstance
一个执行 instanceof 时调用的内部方法,用于改变 instanceof 的运行方式
每个函数都有一个 Symbol.hasInstance 方法,用于确定对象是否为函数的实例。Symbol.hasInstance 方法只接受一个参数,即要检查的值。
// 创建一个特殊数字类,只有1~10的数字才是它的实例
function SpecialNumber(){
}
Object.defineProperty(SpecialNumber, Symbol.hasInstance, {
value: function(v){
return (v instanceof Number) && (v >=1) && (v <= 10)
}
})
let eleven = new Number(11)
let one = new Number(1)
console.log(eleven instanceof SpecialNumber) // false - 11 不在 1~10 的范围内
console.log(one instanceof SpecialNumber) // true - 1 在 1~10 的范围
Symbol.isConcatSpreadable
一个布尔值,表明一个对象是否应该 flattened 为它的数组元素。被 Array.prototype.concat() 使用
传给concat的参数被逐一添加到数组末尾,但数组被区别对待,因为js规范声明,传给concat的数组参数,会自动将它们分解为独立的元素
let arr1 = ['bb', 'cc']
let arr2 = ['aa'].concat(arr1, 'dd')
console.log(arr2) // [ 'aa', 'bb', 'cc', 'dd' ]
禁止区别对待,请看:
let arr1 = ['bb', 'cc']
Object.defineProperty(arr1, Symbol.isConcatSpreadable, {
// 默认是 true
value: false
})
let arr2 = ['aa'].concat(arr1, 'dd')
console.log(arr2) // [ 'aa', [ 'bb', 'cc' ], 'dd' ]
定义了一个类数组对象 obj2,Symbol.isConcatSpreadable 为 true 表明属性值应该被当作独立的元素添加到数组中。请看示例:
let obj = {
0: 'hello',
1: 'aaron',
length: 2
}
let obj2 = {
0: 'hello',
1: 'aaron',
length: 2,
[Symbol.isConcatSpreadable]: true
}
let arr = ['jack'].concat(obj)
let arr2 = ['jack'].concat(obj2)
console.log(arr) // [ 'jack', { '0': 'hello', '1': 'aaron', length: 2 } ]
console.log(arr2) // [ 'jack', 'hello', 'aaron' ]
其他
由于本系列是快速入门,而内置的Symbole值有点对程序编程的味道,剩余的就不在详细介绍。
- 正则表达式 symbols
- Symbol.match : 被String.prototype.match()使用
- Symbol.replace : 被String.prototype.replace()使用
- Symbol.search : 被String.prototype.search()使用
- Symbol.split : 被String.prototype.split()使用
- Symbol.toPrimitive : 对象转为原始值,调用此方法
- Symbol.toStringTag : 被Object.prototype.toString()调用
- Symbol.unscopables : 与 with 相关。如果你不使用with,可以忽略它
- Symbol.iterator : 一个返回迭代器的方法
- Symbol.species : 用于创建派生对象的构造函数
Object.getOwnPropertySymbols()
像 Object.keys()、Object.getOwnPropertyNames()这样的方法不返回任何 Symbol,所以 es6 添加了一个新方法 Object.getOwnPropertySymbols(),用于检索 Symbol 属性。
此方法返回一个给定对象自身的所有 Symbol 属性的数组。请看示例:
let obj = {c: 'c1', d: 'd1'};
let a = Symbol("a");
let b = Symbol.for("b");
obj[a] = "localSymbol";
obj[b] = "globalSymbol";
let objectSymbols = Object.getOwnPropertySymbols(obj);
// 返回Symbol属性的数组
console.log(objectSymbols.length); // 2
console.log(objectSymbols) // [Symbol(a), Symbol(b)]
console.log(objectSymbols[0]) // Symbol(a)
// 不包括Symbol属性
console.log(Object.keys(obj)) // ['c', 'd']
console.log(Object.getOwnPropertyNames(obj)) // ['c', 'd']
其他章节请看:
es6 快速入门 系列 —— Symbol的更多相关文章
- es6 快速入门 系列 —— 类 (class)
其他章节请看: es6 快速入门 系列 类 类(class)是 javascript 新特性的一个重要组成部分,这一特性提供了一种更简洁的语法和更好的功能,可以让你通过一个安全.一致的方式来自定义对象 ...
- es6 快速入门 系列 —— 对象
其他章节请看: es6 快速入门 系列 对象 试图解决的问题 写法繁杂 属性初始值需要重复写 function createPeople(name, age){ // name 和 age 都写了 2 ...
- es6 快速入门 系列 —— 变量声明:let和const
其他章节请看: es6 快速入门 系列 变量声明:let和const 试图解决的问题 经典的 var 声明让人迷惑 function demo1(v){ if(v){ var color='red' ...
- es6 快速入门 系列 —— promise
其他章节请看: es6 快速入门 系列 Promise Promise 是一种异步编程的选择 初步认识Promise 用 Promise 来实现这样一个功能:发送一个 ajax,返回后输出 json ...
- es6快速入门 系列 - async
其他章节请看: es6 快速入门 系列 async 前文我们已经知道 promise 是一种异步编程的选择.而 async 是一种用于执行异步任务更简单的语法. Tip:建议学完 Promise 在看 ...
- es6 快速入门 系列
es6 快速入门(未完结,持续更新中...) 前言 为什么要学习es6 es6对于所有javaScript开发者来说,非常重要 未来,es6将构成javaScript应用程序的基础 es6中很多特性, ...
- es6 快速入门 —— 函数
其他章节请看: es6 快速入门 系列 函数 函数是所有编程语言的重要组成部分,es6之前函数语法一直没什么变化,遗留了许多问题,javaScript开发者多年来不断抱怨,es6终于决定大力度更新函数 ...
- ES6快速入门(二)数据结构
ES6快速入门 一.解构 1. 对象解构 let person = { name: 'Tang', age: 28 }; //必须同名,必须初始化 let {name, age} = person; ...
- python 全栈开发,Day88(csrf_exempt,ES6 快速入门,Vue)
BBS项目内容回顾 1. 登陆页面 1. 验证码 1. PIL(Pillow) 2. io 2. ORM 1. 增删改查 3. AJAX $.ajax({ url: '', type: '', dat ...
- vue 快速入门 系列 —— 侦测数据的变化 - [基本实现]
其他章节请看: vue 快速入门 系列 侦测数据的变化 - [基本实现] 在 初步认识 vue 这篇文章的 hello-world 示例中,我们通过修改数据(app.seen = false),页面中 ...
随机推荐
- 【C】C语言头文件互锁和包含问题
[来源] https://mp.weixin.qq.com/s/4tPHkwEd5n-xHNHJHtCoBw
- OB指定开源版本MySQL模式单节点安装
OB指定开源版本MySQL模式单节点安装 yum源处理 yum install -y yum-utils yum-config-manager --add-repo https://mirrors.a ...
- [转帖]TiDB-merge region相关问题
一.开启region merge # 控制 Region Merge 的 size 上限,当 Region Size 大于指定值时 PD 不会将其与相邻的 Region 合并 pd-ctl confi ...
- [转帖]Redhat 8 磁盘调度策略变化:NOOP改为NONE
说明 在 redhat 4/5/6/7版本中的NOOP调度策略,从8开始修改为NONE,官方解释: none Implements a first-in first-out (FIFO) schedu ...
- 【转帖】You can now run a GPT-3-level AI model on your laptop, phone, and Raspberry Pi
https://arstechnica.com/information-technology/2023/03/you-can-now-run-a-gpt-3-level-ai-model-on-you ...
- [转帖]将 Cloudflare 连接到互联网的代理——Pingora 的构建方式
https://zhuanlan.zhihu.com/p/575228941 简介 今天,我们很高兴有机会在此介绍 Pingora,这是我们使用 Rust 在内部构建的新 HTTP 代理,它每天处理超 ...
- [转帖]使用GCC编译器实测兆芯KX-U6780A的SPEC CPU2006成绩
https://baijiahao.baidu.com/s?id=1722775453962904303 兆芯KX-U6780A是一款8核2.7GHz的使用x86/AMD64指令集(架构)的国产C ...
- [转帖]AMD Zen4 霄龙 9004 转战嵌入式:192 框框无敌!秒杀对手 80%
http://www.myzaker.com/article/64104f50b15ec02eb10eb659 其实,它就是把此前用于服务器.数据中心的霄龙 9004 系列的部分型号拿了过来,命名.规 ...
- [转帖]什么是拒绝服务(DoS)攻击?
https://www.cloudflare.com/zh-cn/learning/ddos/glossary/denial-of-service/ 什么是拒绝服务攻击? 拒绝服务(DoS)攻击是一种 ...
- 简单进行Springboot Beans归属模块单元的统计分析方法
简单进行Springboot Beans归属模块单元的统计分析方法 背景 基于Springboot的产品变的复杂之后 启动速度会越来越慢. 公司同事得出一个结论. beans 数量过多会导致启动速度逐 ...