- 预热
javascript有 6种 数据类型
- undefined
- null
- 布尔值(Boolean)
- 字符串(String)
- 数值(Number)
- 对象(Object)
而 symbol 为ES6新增的数据类型。表示独一无二的值,使用Symbol()定义(S大写!)
- 理解symbol
那么这个symbol到底是个什么东西,我们看下面例子:
const a = Symbol()
const b = Symbol()
console.log(a==b) // false
在我理解,就是对a、b进行随机赋值,并且永远不会重复
再来一个例子
const b = Symbol();
let a = {};
a[b] = 'red';
console.log(a[b]); // red
console.log(a) // {Symbol(): "red"}
a = {
[b]: 'blue',
b: 'black'
}
console.log(a); // {b: "black", Symbol(): "blue"}
a.b = 'yellow'
console.log(a); //{b: "yellow", Symbol(): "blue"}
a[b] = 'black'
console.log(a); //{b: "yellow", Symbol(): "black"}
a['b'] = 'white'
console.log(a); // {b: "white", Symbol(): "black"}
我们可以看到,如果用Symbol()生成的symbol在对象中显示的是Symbol()而不对定义的b,
而需要对symbol值进行修改则需要使用a[b];通过这里我们可以看到symbol的一个使用好处就是不会被不经意的a.b修改了值
- symbol使用
- 写法
let mySymbol = Symbol();
// 第一种写法
let a = {};
a[mySymbol] = 'Hello!';
// 第二种写法
let a = {
[mySymbol]: 'Hello!'
};
// 第三种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
// 以上写法都得到同样结果
a[mySymbol] // "Hello!"
- 添加描述
const sym = Symbol('name');
console.log(sym); // Symbol(name)
定义在Symbol()内添加描述
ES2019 提供方法descripttion
const sym = Symbol('name');
console.log(sym.description); // name
- 赋值
let mySymbol = Symbol();
// 第一种写法
let a = {};
a[mySymbol] = 'Hello!';
// 第二种写法
let a = {
[mySymbol]: 'Hello!'
};
// 第三种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
// 以上写法都得到同样结果
a[mySymbol] // "Hello!"
- 遍历
Symbol 作为属性名,该属性不会出现在for...in、for...of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。但是,它也不是私有属性,有一个Object.getOwnPropertySymbols方法,可以获取指定对象的所有 Symbol 属性名
《ECMAscript 6入门》 ——阮一峰
如果要遍历symbol则需要使用 Object.getOwnPropertySymbols 方法
const a = Symbol('a')
const b = Symbol('b')
const symList = {
[a]: 1,
[b]: 2
}
console.log(Object.getOwnPropertySymbols(symList)); // [Symbol(a), Symbol(b)]
Object.getOwnPropertyNames方法得不到Symbol属性名;
不过,另一个新的 API,Reflect.ownKeys方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。
- Symbol.for(),Symbol.keyFor()
一开始我们说过symbol的概念,symbol为唯一的;但是我们非要使用相同的symbol值呢;
这时候我们就得用 Symbol.for() 了
const a = Symbol.for('c')
const b = Symbol.for('c')
console.log(a == b); // true
console.log(a); // Symbol(c)
获取Symbol.for()定义的描述可以通过 Symbol.keyFor() 来获取,但是如果是通过Symbol()写的描述就获取不到了
const a = Symbol.for("c");
console.log(Symbol.keyFor(a)); // c
const b = Symbol("c");
console.log(Symbol.keyFor(b)); // undefined
- 代码中使用/使用场景
比如我们要进行判断,而判值提前定义为常量
const a = 'NAME_A'
const b = 'NAME_B'
const c = 'NAME_C'
function Func(val) {
switch (val) {
case a:
return 1
case b:
return 2
case c:
return 3
default:
return -1
}
}
console.log(Func(a)); // 1
这里我们并不关心obj里对象值是什么此时我们使用Symbol()
const a = Symbol('a')
const b = Symbol('b')
const c = Symbol('c')
function Func(val) {
switch (val) {
case a:
return 1
case b:
return 2
case c:
return 3
default:
return -1
}
}
console.log(Func(a)); // 1