1. Symbol概念以及引入原因
ES6 引入了的一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
重点:
- Symbol作用:保证每个对象属性的名字都是独一无二的
- Symbol 可以接收字符串作为参数
- Symbol参数(参数为对象会调用toString()作为key;参数相同值也不同;没有参数值也不同)
- Symbol 值不能与其他类型的值进行运算,会报错。
- Symbol 值可以显式转为字符串和布尔值,不能转为Number数值。
- Symbol.iterator属性是一种特殊的key。指向该对象的默认遍历器方法,凡是具有Symbol.iterator属性的对象,都可以使用for...of进行遍历
2.Symbol作用:保证每个对象属性的名字都是独一无二的
问题:对象直接设置key为对象,会将对象调用toString()方法转为[Object,Object],第二个值就覆盖第一个值了
javascript
let obj1 = {a:1}
let obj2 = {a:2}
let obj = {};
// 想要将obj的key设置为obj1的值obj[{a:1}] = 1
obj[obj1] = 1;
obj[obj2] = 2;
// 发现只有一个值,且返回的obj键转成了[object Object],值为2,1被覆盖
console.log(obj);// [object Object] 2
使用Symbol进行定义后,发现就不会被覆盖:
javascript
let obj1 = Symbol({a:1})
let obj2 = Symbol({a:2})
let obj = {};
obj[obj1] = 1;
obj[obj2] = 2;
console.log(obj);
3.Symbol 可以接收字符串作为参数
Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
如下:即使字符串相同,s1和s2也不是一个
javascript
let s1 = Symbol('foo');
let s2 = Symbol('foo');
console.log(s1 === s2); //false
3.Symbol参数(参数为对象会调用toString()作为key;参数相同值也不同;没有参数值也不同)
注意1: Symbol 的参数是一个对象,就会调用该对象的toString方法,将其转为字符串,然后才生成一个 Symbol 值。
注意2:Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。
注意3:Symbol函数的参数没有值也不同
javascript
// 没有参数的情况
let s1 = Symbol();
let s2 = Symbol();
s1 === s2 // false
// 有参数的情况
let s1 = Symbol('foo');
let s2 = Symbol('foo');
s1 === s2 // false
4.Symbol 值不能与其他类型的值进行运算,会报错。
javascript
let sym = Symbol('My symbol');
console.log( "your symbol is " + sym);//Uncaught TypeError: Cannot convert a Symbol value to a string
let num = Symbol(1);
console.log(num+1);Uncaught TypeError: Cannot convert a Symbol value to a string
5.Symbol 值可以显式转为字符串。
javascript
let sym = Symbol('My symbol');
console.log(String(sym));//Symbol(My symbol)
console.log(sym.toString());//Symbol(My symbol)
6.Symbol 值也可以转为布尔值,但是不能转为数值。
javascript
let sym2 = Symbol();
console.log(Boolean(sym2));//true
console.log(!sym2);//false
console.log(Number(sym2));//Uncaught TypeError: Cannot convert a Symbol value to a number
7.Symbol.iterator属性
- 可以看作一种特殊的key
- 对象的Symbol.iterator属性,指向该对象的默认遍历器方法。
- 对象进行for...of循环时,会调用Symbol.iterator方法,返回该对象的默认遍历器。
- 凡是具有Symbol.iterator属性的对象,都可以使用for...of进行遍历
- 如果想让其可以通过for...of进行遍历,就使用Symbol.iterator给其添加一个可遍历的属性
8. Symbol中Object.getOwnPropertySymbols方法获取指定对象的所有 Symbol 属性名。
- Symbol类型时不可枚举的,即属性上有Symbol时,遍历不出来;如果想要获取上面的Symbol属性,就需要使用Object.getOwnPropertySymbols方法。
- Object.getOwnPropertySymbols方法,可以获取指定对象的所有 Symbol 属性名。
- Object.getOwnPropertySymbols方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。
javascript
const obj = {};
let a = Symbol('a');
let b = Symbol('b');
obj[a] = 'Hello';
obj[b] = 'World';
const objectSymbols = Object.getOwnPropertySymbols(obj);
console.log(objectSymbols); //[Symbol(a), Symbol(b)
9.Symbol的实际使用:私有属性;常量枚举
9.1作为常量进行枚举
常量枚举 js没有枚举类型的
javascript
// 常量枚举 js没有枚举类型的
// 产生一个问题 1 2 不能重复 重复的话判断就会出错
// symbol 哪怕你写重复了也没问题
// const CODE_ONE = 1;
// const CODE_TWO = 2;
const CODE_ONE = Symbol(1)
const CODE_TWO = Symbol(2)
console.log(CODE_ONE === CODE_TWO);
9.2作为私有属性:对象进行遍历时,不会遍历具有Symbol类型的数据
对象进行遍历时,不会遍历具有Symbol类型的数据
javascript
// 私有属性
let private = Symbol('private')
var obj = {
_name: '张三',
[private]: '私有的属性',
say: function () {
console.log(this[private])
}
}
console.log(Object.keys(obj))//['_name', 'say']