ES6 学习笔记(八)基本类型Symbol
1、前言
大家都知道,在ES5的时候JavaScript的基本类型有Number、String、Boolean、undefined、object、Null共6种,在es6中,新增了Symbol类型,用于表示独一无二的值。之后又提出了bigInt类型(前面提到过),这里简要的总结Symbol的一些基本用法。
2、基本用法
2.1 用法一(直接使用)
可以直接使用Symbol()创建新的symbol类型,如:
let s = Symbol()
console.log(typeof s); // symbol
注意:
Symbol函数前不能使用new命令,因为生成的Symbol是一个原始类型的值,不是对象。如:
let s = new Symbol("123")
console.log(s);
结果是什么都没输出。
2.2 用法二(接收参数)
Symbol函数可以接收一个字符串作为它的参数,表示对该实例的描述。如:
let s = Symbol("foo")
console.log(typeof s); // symbol
若Symbol函数的参数时一个对象,则会调用它的toString()方法,如:先转化成字符串,再生成一个Symbol值。如:
const obj = {
toString() {
return 'abc'
}
}
const sym = Symbol(obj)
console.log(sym); // Symbol(abc)
由于每个从Symbol()返回的symbol值都是唯一的。一个symbol值能作为对象属性的标识符;因此下面的结果都是false。
let s1 = Symbol()
let s2 = Symbol()
let s3 = Symbol(undefined)
let s4 = Symbol(undefined)
console.log("s1==s2", s1 == s2); // s1==s2 false
console.log("s3==s4", s3 == s4); // s3==s4 false
console.log(Symbol("foo") == Symbol("foo")); // false
- 注意:
Symbol值不能与其他类型的值进行运算,否则会报错。
Symbol值可以显式的转换为字符串。
Symbol值可以显式的转换为布尔值,但不能转换为数值。
2.3 用法三(作为属性名)
Symbol作为对象属性名保证不会出现同名的属性。对于对象中的键名十分有效,能够保证他们不被修改。如:
let proSym = Symbol()
let obj = {}
obj.proSym = "hello" // 作为数据属性使用
console.log(obj[proSym]); // undefined
console.log(obj['proSym']); // hello
注意:
当Symbol作为属性名时不能使用点运算符。
在对象内部使用Symbol值定义属性时,Symbol值必须放在方括号中。
2.4 用法四(作为方法)
Symbol 可用于定义方法
let proSym = Symbol()
let obj = {
[proSym](name){
console.log('hello,'+name);
}
}
obj[proSym]("Marry") // hello,Marry
2.5 用法四(定义常量)
Symbol 可以用来定义一组常量,保证这组的常量值都不相等
const COLOR_RED = Symbol();
const COLOR_GREEN = Symbol();
function getComplements(color) {
switch (color) {
case COLOR_RED:
console.log('color is red');
break;
case COLOR_GREEN:
console.log('color is green');
break;
default:
throw new Error('Undefined color');
}
}
getComplements(COLOR_GREEN);
getComplements(123456);
输出结果:
color is green
Error: Undefined color
3、属性名遍历
Symbol作为对象中的属性名时,可以通过Object.getOwnPropertySymbols()方法获取。该方法返回的是一个数组,包含当前对象所有用做属性名的Symbol值。如:
let obj = {}
let a = Symbol('a')
let b = Symbol('b')
obj[a] = 'Hello'
obj[b] = 'World'
let objectSymbols = Object.getOwnPropertySymbols(obj)
console.log(objectSymbols);
输出结果:
[ Symbol(a), Symbol(b) ]
另外的几种方法:
- Object.defineProperty() 直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
- Object.getOwnPropertyNames() 返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
let obj = {};
let a = Symbol('a');
let b = Symbol('b');
obj[a] = 'Hello';
obj[b] = 'World';
let foo = Symbol('foo');
Object.defineProperty(obj, foo, {
value: 'foobar'
});
for (let i in obj) {
console.log(i);
}
let r1 = Object.getOwnPropertyNames(obj);
console.log(r1);
let r2 = Object.getOwnPropertySymbols(obj);
console.log(r2);
输出结果:
{ [Symbol(a)]: 'Hello', [Symbol(b)]: 'World' }
[]
[ Symbol(a), Symbol(b), Symbol(foo) ]
空
4、Reflect.ownKeys()方法
Reflect.ownKeys方法可以返回所有类型的键名,包括常规键名和Symbol键名。如:
let obj = {
[Symbol('my key')]: 1,
enum: 2,
notenum: 3
}
let s= Reflect.ownKeys(obj)
console.log(s);
输出结果:
[ 'enum', 'notenum', Symbol(my key) ]
5、Symbol.for()与Symbol.keyFor()方法
1、Symbol.for(key)方法会根据给定的key从symbol 注册表中找到对应的 symbol,如果找到了,则返回它,否则,新建一个与该key相关联的 symbol,并放入全局 symbol 注册表中。如:
let s1 = Symbol.for("foo");
let s2 = Symbol.for("foo");
console.log(s1 == s2);
上面的s1指的是创建一个键名为foo的Symbol放入Symbol注册表中,s2指的是从Symbol注册表中取出键名为foo的Symbol。两者是同一个,所以输出结果是true。
2、Symbol.keyFor(sym) 方法用来获取全局symbol 注册表中与某个 symbol 关联的键。若查找到该symbol,则返回该symbol的key值,否则返回undefined。如:
let s3 = Symbol.for("food");
console.log(Symbol.keyFor(s3));
console.log(Symbol.keyFor(Symbol.iterator));
输出结果:
food
undefined
6、消除魔术字符串
魔术字符串,是指在代码中多次出现且与代码形成强耦合的某一个具体的字符串或数值。为了尽量减少这种情况,应该由变量代替这些具体的字符串或数值。
6.1 实例1:计算三角形和正方形的面积
function getArea(shape, options) {
let area = 0;
switch (shape) {
case 'Triangle':
area = 0.5 * options.width * options.height;
break;
case 'Square':
area = options.height ** 2;
break;
default:
throw new Error('undefined shape');
}
return area;
}
let r1 = getArea('Triangle', { width: 100, height: 100 });
console.log(r1);
let r2 = getArea('Square', { width: 100, height: 100 });
console.log(r2);
运行结果:
5000
10000
可以看到,上面代码中的Triangle与Square都是魔术字符串,那么怎么消除它们呢
6.2 实例2:计算三角形和正方形的面积
通过变量来代替字符串,如:
let shapeType = {
triangle: 'Triangle',
square: 'Square'
};
function getArea(shape, options) {
let area = 0;
switch (shape) {
case shapeType.triangle:
console.log(shapeType.triangle);
area = 0.5 * options.width * options.height;
break;
case shapeType.square:
console.log(shapeType.square);
area = options.height ** 2;
break;
default:
throw new Error('undefined shape');
}
return area;
}
let r1 = getArea(shapeType.triangle, { width: 100, height: 100 });
console.log(r1);
let r2 = getArea(shapeType.square, { width: 100, height: 100 });
console.log(r2);
输出结果:
Triangle
5000
Square
10000
6.3 实例3:计算三角形和正方形的面积
还可以通过Symbol()代替字符串,如:
let shapeType = {
triangle: Symbol(),
square: Symbol()
}
function getArea(shape, options) {
let area = 0;
switch (shape) {
case shapeType.triangle:
console.log(shapeType.triangle);
area = 0.5 * options.width * options.height;
break;
case shapeType.square:
console.log(shapeType.square);
area = options.height ** 2;
break;
default:
throw new Error("undefind shape")
}
return area
}
let r1 = getArea(shapeType.triangle, { width: 100, height: 100 });
console.log(r1);
let r2 = getArea(shapeType.square, { width: 100, height: 100 });
console.log(r2);
输出结果:
Symbol()
5000
Symbol()
10000
ES6 学习笔记(八)基本类型Symbol的更多相关文章
- 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学习笔记-class之一概念
前段时间复习了面向对象这一部分,其中提到在es6之前,Javasript是没有类的概念的,只从es6之后出现了类的概念和继承.于是乎,花时间学习一下class. 简介 JavaScript 语言中,生 ...
- JS&ES6学习笔记(持续更新)
ES6学习笔记(2019.7.29) 目录 ES6学习笔记(2019.7.29) let和const let let 基本用法 let 不存在变量提升 暂时性死区 不允许重复声明 块级作用域 级作用域 ...
- ES6学习笔记<四> default、rest、Multi-line Strings
default 参数默认值 在实际开发 有时需要给一些参数默认值. 在ES6之前一般都这么处理参数默认值 function add(val_1,val_2){ val_1 = val_1 || 10; ...
- ES6学习笔记<二>arrow functions 箭头函数、template string、destructuring
接着上一篇的说. arrow functions 箭头函数 => 更便捷的函数声明 document.getElementById("click_1").onclick = ...
- 【opencv学习笔记八】创建TrackBar轨迹条
createTrackbar这个函数我们以后会经常用到,它创建一个可以调整数值的轨迹条,并将轨迹条附加到指定的窗口上,使用起来很方便.首先大家要记住,它往往会和一个回调函数配合起来使用.先看下他的函数 ...
- ES6学习笔记之块级作用域
ES6学习笔记:块级作用域 作用域分类 全局作用域 局部作用域 块级作用域 全局作用域示例 var i=2; for (var i = 0; i < 10; i++) { } console.l ...
- go微服务框架kratos学习笔记八 (kratos的依赖注入)
目录 go微服务框架kratos学习笔记八(kratos的依赖注入) 什么是依赖注入 google wire kratos中的wire Providers injector(注入器) Binding ...
- ES6学习笔记之变量的解构赋值
变量的解构赋值 ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构. 数组的解构赋值 以前,为变量赋值,只能直接指定值: 1 2 3 var a = 1; var b = 2; ...
随机推荐
- 浅拷贝工具类,快速将实体类属性值复制给VO
/** * 浅拷贝的工具类 */ public class PropertiesUtil { /** * 两个类,属性名一样的元素,复制成员. */ public static void copy(O ...
- virtio_net设备的校验和问题
我们来看一个virtio_net设备的校验和配置: [root@10 ~]# ethtool -K eth0 tx-checksumming on //caq:大写的K用来调整feature [roo ...
- 【python】pandas 索引操作
选择.修改数据(单层索引) 推荐使用.at..iat..loc..iloc 操作 句法 结果 备注 选择列 df[col] Series 基于列名(列的标签),返回Series 用标签选择行 df.l ...
- 不想当Window的Dialog不是一个好Modal,弹窗翻身记
弹窗是我们熟视无睹的一种交互方式,经常用到,但从没好好想过这种交互行为背后的意义... 弹窗是Windows的灵魂 Windows的灵魂是什么?当然是Window,当方便快捷的多窗口进入人们视野的时候 ...
- Android、iOS平台RTMP/RTSP播放器实时音量调节
介绍移动端RTMP.RTSP播放器实时音量调节之前,我们之前也写过,为什么windows播放端加这样的接口,windows端播放器在多窗口大屏显示的场景下尤其需要,尽管我们老早就有了实时静音接口,相对 ...
- 【多服务场景化解决方案】智能家居(UrbanHome)
介绍 UrbanHome是一款提供房屋维修服务的移动应用.如有维修需求,用户可通过该应用联系所在城市的管道工,电工,保洁,漆匠,木匠,修理工等,或是搜寻导航附近的维修商店. 通过构建UrbanHo ...
- KingbaseES V8R3集群管理和维护案例之---failover切换wal日志变化分析
案例说明: 本案例通过对KingbaseES V8R3集群failover切换过程进行观察,分析了主备库切换后wal日志的变化,对应用者了解KingbaseES V8R3(R6) failover ...
- KingbaseES V8R3 由于修改系统时间导致sys_rman备份故障案例
案例说明: 此案例,为复现"current time may be rewound"错误.对于数据库环境,在使用前必须保证系统时间的正确性.如果数据库创建后,再将系统时间修改为 ...
- SpringBoot_事务总结
Springboot 事务 1. 打印SQL 日志的两种配置方式 [1]通过配置包的log等级来打印SQL日志,但这种不会打印出事务日志 logging.level.com.grady.mybatis ...
- K8S name_namespace
Name 由于K8S内部,使用"资源"来定义每一种逻辑概念(功能),故没种"资源",都应该有自己的"名称" "资源"有 ...