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; ...
随机推荐
- SpringBoot RabbitMQ 注解版 基本概念与基本案例
前言 人间清醒 目录 前言 Windows安装RabbitMQ 环境工具下载 Erlang环境安装 RabbitMQ安装 RabbitMQ Web管理端安裝 RabbitMQ新增超级管理员 Rabbi ...
- 创建deploymen的几种方式
创建deployment方式有两种,一种是命令直接创建,一种是使用yaml文件 1. 直接使用命令方式: --record 参数用来记录版本,也可以忽略,建议带上 kubectl create dep ...
- 长篇图解etcd核心应用场景及编码实战
大家好啊,我是字母哥,今天写一篇关于etcd的文章,其实网上也有很多关于etcd的介绍,我就简明扼要,总结提炼,期望大家通过这一篇文章掌握etcd的核心知识以及编码技能! 本文首先用大白话给大家介绍一 ...
- 第三十八篇:vue3路由
好家伙,水博客怎么说 1.0.安装:简简单单的淘宝镜像安装 装一下淘宝镜像(一般都有) npm install -g cnpm --registry=https://registry.npm.taob ...
- 《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(17)-Fiddler如何充当第三者,再识AutoResponder标签-下篇
1.简介 上一篇宏哥主要讲解的一些在电脑端的操作和应用,今天宏哥讲解和分享一下,在移动端的操作和应用.其实移动端和PC端都是一样的操作,按照宏哥前边抓取移动端包设置好,就可以开始实战了. 2.界面功能 ...
- 可别小看了XSS漏洞
可别小看了XSS漏洞 对于初了解xss漏洞的人来说,XSS漏洞的危害就是获取受害者的cookie,来进行 'cookie劫持'. 今天就总结一下XSS漏洞的危害性,望安全人员不要轻视,开发人员 ...
- js函数( 普通函数、箭头函数 ) 内部this的指向
- 普通函数 | 具名普通函数.匿名普通函数,在不作为对象的属性值的情况下,其内部的 this 总是指向代码运行环境下的全局对象 ( 例如,浏览器中的 window ). 示例: (functio ...
- KingbaseES 局部索引
一个列要不要建立btree索引,判断条件是其键值分布是否够离散,比如主键.唯一键,可以建立索引.如果这个列有大量重复的值,则建立索引没有意义. 在生产环境中常会碰到键值分布不均匀的列,如表t1有一个名 ...
- Hint 使用--leading
Oracle hint -- leading 的作用是提示优化器某张表先访问,可以指定一张或多张表,当指定多张表时,表示按指定的顺序访问这几张表.而 Postgresql leading hint的功 ...
- SDUT 2022 Autumn Team Contest 7th
1.J题:给你T组数据,每一组数据给你一个区间,让你求这个区间的范围,区间的起始时间和终止时间可能被包含或重复 思路:思路的话,就是直接把给定的两个区间的之间的数包括端点存到vector去重,然后直接 ...