ES6学习笔记(八)第七种类型Symbol
1.概述
ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是 ES6 引入Symbol
的原因。
ES6 引入了一种新的原始数据类型Symbol
,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined
、null
、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
Symbol 值通过Symbol
函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
let s = Symbol(); typeof s
// "symbol"
上面代码中,变量s
就是一个独一无二的值。typeof
运算符的结果,表明变量s
是 Symbol 数据类型,而不是字符串之类的其他类型。
注意,Symbol
函数前不能使用new
命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。
Symbol
函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
let s1 = Symbol('foo');
let s2 = Symbol('bar'); s1 // Symbol(foo)
s2 // Symbol(bar) s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"
Symbol 值不能与其他类型的值进行运算,会报错。
但是,Symbol 值可以显式转为字符串。
另外,Symbol 值也可以转为布尔值,但是不能转为数值。
2.作为属性名的 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!"
上面代码中,因为点运算符后面总是字符串,所以不会读取mySymbol
作为标识名所指代的那个值,导致a
的属性名实际上是一个字符串,而不是一个 Symbol 值。
同理,在对象的内部,使用 Symbol 值定义属性时,Symbol 值必须放在方括号之中。
let s = Symbol(); let obj = {
[s]: function (arg) { ... }
}; obj[s](123);
上面代码中,如果s
不放在方括号中,该属性的键名就是字符串s
,而不是s
所代表的那个 Symbol 值。所以Symbol 值s是一个变量,指向Symbol ();
常量使用 Symbol 值最大的好处,就是其他任何值都不可能有相同的值了,因此可以保证上面的switch
语句会按设计的方式工作。
还有一点需要注意,Symbol 值作为属性名时,该属性还是公开属性,不是私有属性。
也就是说,Symbol 用于独一无二的区别,但是并不关心其具体的表示的含义情况,可以将其看作一个UUID。
4.属性名的遍历
Symbol 作为属性名,该属性不会出现在for...in
、for...of
循环中,也不会被Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回。但是,它也不是私有属性,有一个Object.getOwnPropertySymbols
方法,可以获取指定对象的所有 Symbol 属性名。
5.Symbol.for(),Symbol.keyFor()
有时,我们希望重新使用同一个 Symbol 值,Symbol.for
方法可以做到这一点。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建并返回一个以该字符串为名称的 Symbol 值。
let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo'); s1 === s2 // true
上面代码中,s1
和s2
都是 Symbol 值,但是它们都是同样参数的Symbol.for
方法生成的,所以实际上是同一个值。
Symbol.for()
与Symbol()
这两种写法,都会生成新的 Symbol。它们的区别是,前者会被登记在全局环境中供搜索,后者不会。Symbol.for()
不会每次调用就返回一个新的 Symbol 类型的值,而是会先检查给定的key
是否已经存在,如果不存在才会新建一个值。比如,如果你调用Symbol.for("cat")
30 次,每次都会返回同一个 Symbol 值,但是调用Symbol("cat")
30 次,会返回 30 个不同的 Symbol 值。
Symbol.keyFor
方法返回一个已登记的 Symbol 类型值的key
。
let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo" let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined
上面代码中,变量s2
属于未登记的 Symbol 值,所以返回undefined
。
需要注意的是,Symbol.for
为 Symbol 值登记的名字,是全局环境的,可以在不同的 iframe 或 service worker 中取到同一个值。
总之:Symbol.for---创建并登记
其他方法...
ES6学习笔记(八)第七种类型Symbol的更多相关文章
- ES6 学习笔记(四)基本类型Number
1.数值 1.1 .JavaScript数值的特点 不区分整数值和浮点数值. 所有数值均用浮点数值表示. 采用IEEE-754标准定义的64位浮点数格式表示. 整数在实际操作时(如数组索引),则是基于 ...
- ES6学习笔记八(module模块export)
1.导出export,导入import组合 知识点1:导出export lesson2.js export let A=; export function test(){ console.log('t ...
- ES6学习笔记八:类与继承
一:Class ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板.通过class关键字,可以定义类. 定义“类”的方法的时候,前面不需要加上function这个关键 ...
- ES6 学习笔记(六)基本类型String
字符串String 1.字面量 需要注意的地方: 由单引号或双引号括起来的字符序列. 单双引号可以嵌套,由最外围引号定界字符串 字符串字面量可以拆分成数行,每行必须以反斜线(\)结束,且反斜线都不计入 ...
- ES6 学习笔记(五)基本类型Boolean
Boolean 1.需要注意的地方: 取值:true false 对于值为空字符串,0,-0,NaN,Null,undefined,false的布尔对象,它都会有一个初始值false.对于其它的值如& ...
- python学习笔记八--动态类型
一.变量,对象,引用: 1. 变量: 2. 对象:均包含了一个头部信息,有以下两部分内容 a.对象的数据类型, b.引用计数器:纪录当前引用货指向该对象的数量,一旦计数器被清零,该对象的内存空间就会被 ...
- 【Unity Shaders】学习笔记——SurfaceShader(七)法线贴图
[Unity Shaders]学习笔记——SurfaceShader(七)法线贴图 转载请注明出处:http://www.cnblogs.com/-867259206/p/5627565.html 写 ...
- es6学习笔记-class之一概念
前段时间复习了面向对象这一部分,其中提到在es6之前,Javasript是没有类的概念的,只从es6之后出现了类的概念和继承.于是乎,花时间学习一下class. 简介 JavaScript 语言中,生 ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第七章:在Direct3D中绘制(二)
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第七章:在Direct3D中绘制(二) 代码工程地址: https:/ ...
随机推荐
- 面试题——ArrayList和LinkedList的区别
List概括 先回顾一下List在Collection的框架图: 从图中可以看出: List是一个接口,他继承Collection接口,代表有序的队列. AbstractList是一个抽象类, ,它继 ...
- 严重: 文档无效: 找不到语法。 at (null:2:19)
1.错误描写叙述 严重: 文档无效: 找不到语法. at (null:2:19) org.xml.sax.SAXParseException; systemId: file:/D:/MyEclipse ...
- Linux下PHP开启Oracle支持(oci8)
使用php的常见问题是:编译php时忘记加入某扩展,后来想加入扩展,可是由于安装php后又装了一些东西如PEAR等,不想删除文件夹重装,那么此时就须要自己又一次添加某模块支持了,Linux操作系统下能 ...
- JNI之——'cl' 不是内部或外部命令,也不是可执行的程序或批处理文件
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46604315 问题的出现: 今天卸载了VS2010,重装vs2008后.发 ...
- phpcms v9会员推荐位
模版显示推荐会员代码 <div class="zhanxun2"> <div class="title"> ...
- dom4j组装xml 以及解析xml
dom4j组装xml 以及解析xml: 1.下载dom4j的jar包,地址:https://dom4j.github.io/ 2.java代码: package test; import java.i ...
- <Sicily>Greatest Common Divisors
一.题目描述 A common divisor for two positive numbers is a number which both numbers are divisible by. It ...
- PHP接收GET中文参数乱码的原因及解决方案
方案1: $str = iconv("gb2312","utf-8",$str); 方案2: mb_convert_encoding($str, "u ...
- mac本 maven项目还没发布成功,tomcat就报没有监听ContextLoaderListener 的解决方法
Maven项目下update maven后Eclipse报错:java.lang.ClassNotFoundException: ContextLoaderL 严重: Error config ...
- Python3基础笔记--生成器
目录: 一.列表生成器 二.生成器 三.迭代器 一.列表生成器 a = [x for x in range(10)] b= [y*2 for y in range(10)] def f(n) retu ...