Symbol基本数据类型

发布于:2022-12-16 ⋅ 阅读:(484) ⋅ 点赞:(0)

目录

前言

一、创建Symbol值

二、Symbol数据类型的作用

1、解决命名冲突

2、消除魔术字符串

三、全局注册表


前言

ES6引入的一种新的原始数据类型Symbol,表示独一无二的值。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数据类型的作用

1、解决命名冲突

例子:
当我们想要给一个对象添加新属性时,如果我们担心属性名重名,就可以使用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]]

2、消除魔术字符串

魔术字符串指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。

例子:
我们封装一个求各种图形的面积的函数,代码如下所示:

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

本文含有隐藏内容,请 开通VIP 后查看