你一闭眼世界就黑了,你不是主角是什么?
目录
什么是Symbol?
ES6引入了一种新的原始数据类型 Symbol
,表示独一无二的值,它属于JavaScript语言的原生数据类型之一。
其他数据类型是: Undefined
、Null
、布尔值(Boolean
)、字符串(String
)、数值(Number
)、对象(Object
)。
Symbol特点:
- 由于每一个Symbol值都是不相等的,这意味着Symbol值可以作为标识符,用于对象的属性名,保证不会出现同名的属性。
- Symbol主要用于对象属性的唯一性标识,可以解决属性名冲突的问题。
创建方法:
let s1 = Symbol(); // 生成了一个symbol类型的数据
console.log(typeof s1); // symbol
每次创建都会生成一个独一无二的值:
let s1 = Symbol(); // 生成了一个symbol类型的数据
let s2 = Symbol();
console.log(s1 === s2); // false
注意点:
不能进行运算:
Symbol数据类型在JavaScript中是不能进行常规的数学运算的,包括加法(+)、减法(-)、乘法(*)、除法(/)以及比较运算(>、<、>=、<=)等。
let s1 = Symbol();
console.log(s1 + 'aaaa');// es6.html:16 Uncaught TypeError: Cannot convert a Symbol value to a string
显示调用toString() --没有意义
let s1 = Symbol();
console.log(s1.toString()); // Symbol()
console.log(s1.toString() + 'aaa'); // Symbol()aaa
隐式转换boolean
let s1 = Symbol();
// 这里的s1相当于true
if (s1) {
console.log('执行');
}
如果属性名冲突了怎么办?
obj.name和obj[name]的区别:
let obj = {
name: 'sssssy',
getName() {
console.log(this.name);
}
}
let name = Symbol();
obj[name] = 'kitty'
console.log(obj);
console.log(obj.name); //sssssy
console.log(obj[name]); // kitty
变量命名:
所以写库的作者会尽量避免直接.xxx来进行命名:
let name = Symbol();
let age = Symbol();
let obj = {
[name]: 'sssssy',
[age]: 100
}
console.log(obj);
避免直接写Symbol()代替变量:
避免变量直接写 Symbol():
let obj = {
[Symbol()]: '123', //这样虽然可以创建一个独一无二的值,但是访问不了。
}
console.log(obj[Symbol()]); // undefined 因为这里类似于创建了一个新的Symbol类型。
整合变量:
如果变量过多,也可以这样来写:
let keys = {
name: Symbol(),
age: Symbol(),
loacation: Symbol(),
test: Symbol(),
}
let obj = {
[keys.name]: 'sssssy',
[keys.age]: 18,
[keys.loacation]: '北京',
[keys.test]() {
console.log('test');
}
}
console.log(obj);
console.log(obj[keys.name]); // sssssy
obj[keys.test](); // test
接受传参:
由于展开全是Symbol(),我不知道是哪个变量,所以可以往Symbol()的括号里面添加参数【接受传参】,让我们能看出是哪个变量:
let keys = {
name: Symbol("name"),
age: Symbol("age"),
loacation: Symbol("location"),
test: Symbol("test"),
}
let obj = {
[keys.name]: 'sssssy',
[keys.age]: 18,
[keys.loacation]: '北京',
[keys.test]() {
console.log('test');
}
}
console.log(obj);
不能进行for in 循环:
let keys = {
name: Symbol("name"),
age: Symbol("age"),
loacation: Symbol("location"),
test: Symbol("test"),
}
let obj = {
name: '普通属性',
[keys.name]: 'sssssy',
[keys.age]: 18,
[keys.loacation]: '北京',
[keys.test]() {
console.log('test');
}
}
for (let i in obj) {
console.log(i);
}
只能打印出普通属性。。。
那该怎么办呢?
使用Object.getOwnPropertySymbols() 可以拿到所有的Symbol属性
Object.getOwnPropertySymbols():
let keys = {
name: Symbol("name"),
age: Symbol("age"),
loacation: Symbol("location"),
test: Symbol("test"),
}
let obj = {
name: '普通属性',
[keys.name]: 'sssssy',
[keys.age]: 18,
[keys.loacation]: '北京',
[keys.test]() {
console.log('test');
}
}
console.log(Object.getOwnPropertySymbols(obj));
跪求既能拿到普通属性,又能拿到Symbol属性的方法!!!
好的。。平身。。。
就是使用:Reflect.ownKeys()
let keys = {
name: Symbol("name"),
age: Symbol("age"),
loacation: Symbol("location"),
test: Symbol("test"),
}
let obj = {
name: '普通属性',
[keys.name]: 'sssssy',
[keys.age]: 18,
[keys.loacation]: '北京',
[keys.test]() {
console.log('test');
}
}
console.log(Reflect.ownKeys(obj));
老铁们把666打到公屏上!! 66666~6666~6666~
Reflect.ownKeys() 遍历属性名和属性值:
包含所有普通属性的和Symbol属性的:
let keys = {
name: Symbol("name"),
age: Symbol("age"),
loacation: Symbol("location"),
test: Symbol("test"),
}
let obj = {
name: '普通属性',
[keys.name]: 'sssssy',
[keys.age]: 18,
[keys.loacation]: '北京',
[keys.test]() {
console.log('test');
}
}
Reflect.ownKeys(obj).forEach(item => {
console.log(item, obj[item]);
})
作为常量:
正常调用:
function play(type) {
switch (type) {
case 1:
console.log('视频播放');
break;
case 2:
console.log('音频播放');
break;
case 3:
console.log('图片播放');
break;
}
}
play(1) // 视频播放
play(2) // 音频播放
play(3) // 图片播放
1 2 3这样数字写的用户不理解,我们把它们换成可理解的:
但是这样如果我提前知道这些数字,依旧可以通过数字去调用到
const VIDEO = 1;
const AUDIO = 2;
const IMAGE = 3;
function play(type) {
switch (type) {
case VIDEO:
console.log('视频播放');
break;
case AUDIO:
console.log('音频播放');
break;
case IMAGE:
console.log('图片播放');
break;
}
}
play(VIDEO) // 视频播放
play(1) // 视频播放
这时候就可以使用Symbol作为一个常量:(也就是作为一种应用,统一代码的一致性)
const VIDEO = Symbol();
const AUDIO = Symbol();
const IMAGE = Symbol();
function play(type) {
switch (type) {
case VIDEO:
console.log('视频播放');
break;
case AUDIO:
console.log('音频播放');
break;
case IMAGE:
console.log('图片播放');
break;
}
}
play(VIDEO) // 视频播放
play(1) // 什么都没有