目录
ES6引入的一种新的原始数据类型Symbol,表示独一无二的值。Symbol函数可以接受参数,表示对于这个唯一值的描述,属于基本数据类型,Symbol()函数会返回symbol类型的值。
Symbol是一个函数,不需要使用new关键字来创建
- let sy1 = Symbol();
- console.log(sy1); //Symbol()
- console.log(typeof sy1); //symbol
Symbol函数还可以接收参数:
- let sy1 = Symbol('hello');
- console.log(sy1); //Symbol(hello)
- console.log(typeof sy1); //symbol
Symbol表示独一无二的值,即使取一样的参数,两个变量也不相等
- let sy1 = Symbol('hello')
- let sy2 = Symbol('hello')
- console.log(sy1 === sy2); //false
例子:
当我们想要给一个对象添加新属性时,如果我们担心属性名重名,就可以使用Symbol数据类型。
- // 声明两个Symbol类型的变量
- let sy1 = Symbol('name');
- let sy2 = Symbol('age');
- let obj = {
- name: "zhangsan",
- age: 12,
- // 属性名是变量名时使用中括号
- [sy1]: 'lisi',
- [sy2]: 18,
- [Symbol('email')]: '888888@qq.com'
- };
-
- // 访问方式,用中括号访问
- console.log(obj[sy1]); //lisi
- console.log(obj[sy2]); //18
- console.log(obj[Symbol('email')]); //undefined
注意:当属性名是变量时,我们需要使用中括号括起来。
访问方式也是直接使用中括号访问。
上述代码,我们可以使用中括号访问到sy1和sy2,但是访问不到 [Symbol('email')],这时候我们可以通过Object.getOwnPropertySymbols()方法来访问该属性值,该方法返回一个包含给定对象所有自有的Symbol值的属性(包括不可枚举的Symbol值属性)组成的数组。
- let res = Object.getOwnPropertySymbols(obj)
- console.log(res); //[ Symbol(name), Symbol(age), Symbol(email) ]
- console.log(obj[res[2]]); //888888@qq.com
注意:使用for...in循环访问不到symbol值
- for(let key in obj){
- console.log(key);
- }
-
- 输出结果:
- name
- age
总结:
1、for in循环访问不到symbol值
2、获取symbol变量/值,使用getOwnPropertySymbols方法
3、如何访问属性对应属性值 obj[res[1]]
魔术字符串指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。
例子:
我们封装一个求各种图形的面积的函数,代码如下所示:
- function test(shape, options) {
- let area = 0;
- switch (shape) {
- case 'triangle':
- area = .5 * options.width * options.height;
- break;
- case 'square':
- area = options.width * options.height;
- break;
- case 'circle':
- area = Math.PI * Math.pow(options.r, 2);
- break;
- default:
- area = -1;
- }
- return area
- }
-
- console.log(test('triangle', {width: 100, height: 100, r: 100}));
可以看到代码中多次出现了具体的字符串,但我们改变函数中的字符串时,那么调用函数时的实参也需要做出改变,这样并不方便,而且如果我们要求更多图形的面积,那么我们命名的字符串很有可能会发生重复,这样调用函数就会得到错误的结果。

因此我们最好使用变量替代这些字符串:
- function test(shape, options) {
- let area = 0;
- switch (shape) {
- case Shape.triangle:
- area = .5 * options.width * options.height;
- break;
- case Shape.square:
- area = options.width * options.height;
- break;
- case Shape.circle:
- area = Math.PI * Math.pow(options.r, 2);
- break;
- default:
- area = -1;
- }
- return area
- }
- let Shape = {
- triangle: Symbol('三角形'),
- square: Symbol('三角形'),
- circle: Symbol('圆形')
- }
- console.log(test(Shape.triangle, {width: 100, height: 100, r: 100}));

与Symbol() 不同的是,用 Symbol.for() 方法创建的 symbol 会被放入一个全局 symbol 注册表中。Symbol.for() 并不是每次都会创建一个新的 symbol,它会首先检查给定的 key 是否已经在注册表中了。假如是,则会直接返回上次存储的那个。否则,它会再新建一个。
例子:
不使用Symbol.for() 方法:
- let sy1 = Symbol('one');
- let sy2 = Symbol('one');
- console.log(sy1 === sy2); //false
使用Symbol.for() 方法:
- let sy1 = Symbol.for('one');
- let sy2 = Symbol.for('one');
- console.log(sy1 === sy2); //true
我们可以使用Symbol.keyFor()方法检测symbol值是否在全局注册表中注册过。返回对于symbol的描述或者undefined
- let sy1 = Symbol.for('hello');
- console.log(Symbol.keyFor(sy1)); //hello
- let sy2 = Symbol('world');
- console.log(Symbol.keyFor(sy2)) //undefined