current position:Home>The Symbol explanation of JS data types

The Symbol explanation of JS data types

2022-09-23 10:18:48Luo Li

1、Symbol概述

ES6 引入的一种新的原始数据类型Symbol,表示独一无二的值.

它属于JavaScriptOne of the language of the native data types,其他数据类型是:undefined、null、Boolean、String、Number、Bigint、Object.

使用场景:

ES5 的对象属性名都是字符串,这容易造成属性名的冲突.

比如,你使用了一个他人提供的对象,Do you want to add a new method for the object(mixin模式),This time the name of the new method could and existing method zhangs,这个时候就可以使用Symbol,To prevent your new additional method zhangs.


2、Symbol的特性

let s = Symbol();
console.log(typeof s); // symbol

上述代码,s就是一个独一无二的值.

注意:Symbol()Function cannot be used beforenew命令,否则会报错.这是因为生成的Symbol是一个原始类型的值,而不是对象.另外,由于Symbol值不是对象,So can't add properties.Basically it is a kind ofSimilar to the string data type.


let s1 = Symbol('s1');
let s2 = Symbol('s2');
console.log(s1, s2); // Symbol(s1) Symbol(s2)
console.log(s1.toString(), s2.toString()); // "Symbol(s1)" "Symbol(s2)"

Symbol()函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述.

This is mainly to show the console,Or converted to a string,比较容易区分.

注意:Symbol()函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的.


let obj = {
    toString: function() {
        return 'abc';
    }
}

console.log(Symbol(obj)); // abc

let s = Symbol('mySymbol');

// console.log(s + '123'); // Uncaught TypeError: Cannot convert a Symbol value to a string
console.log(String(s), s.toString()); // 'Symbol(mySymbol)' 'Symbol(mySymbol)'
console.log(Boolean(s)); // true
console.log(Number(s)); // Uncaught TypeError: Cannot convert a Symbol value to a number

当SymbolWhen the parameters of the function is an object,Automatically call objecttoString方法,After converted to string,Put the string as a parameter to perform.

Symbol可以转成字符串、布尔值,不能转成数字,Also can't and other operations of the value of the type.


3、Symbol.prototype.description

ES2019提供了一个SymbolThe value of the instance attributesdescription,可以直接返回Symbol值的描述.

let s = Symbol('my symbol')

console.log(s.description); // my symbol

4、Symbol作为对象属性名

由于每一个 Symbol 值都是不相等的,这意味着只要 Symbol Value as identifier,用于对象的属性名,就能保证不会出现同名的属性.

let mySymbol = Symbol('mySymbol');

// 第一种写法
let a = {};
a[mySymbol] = 'hello Symbol';

// 第二种写法
let b = {
    [mySymbol]: 'hello Symbol'
}

// 第三种写法
let c = {};
Object.defineProperty(c, mySymbol, { value: 'hello Symbol' });

console.log(a, b, c);

注意:Symbol 值作为对象属性名时,不能用点运算符.

因为点运算符后面总是字符串,所以不会读取mySymbol作为标识名所指代的那个值.

还有一点需要注意,Symbol 值作为属性名时,该属性还是公开属性,不是私有属性.


5、Symbol作为常量

Symbol 类型还可以用于定义一组常量,保证这组常量的值都是不相等的.

const log = {};

log.levels = {
    DEBUG: Symbol('debug'),
    INFO: Symbol('info'),
    WARN: Symbol('warn')
};
console.log(log.levels.DEBUG, 'debug message');
console.log(log.levels.INFO, 'info message');

6、消除魔术字符串

魔术字符串指的是,在代码之中多次出现、Form a strong coupling with the code的某一个具体的字符串或者数值.风格良好的代码,应该尽量消除魔术字符串,改由含义清晰的变量代替.

function getArea(shape, options) {
  let area = 0;

  switch (shape) {
    case 'Triangle': // 魔术字符串
      area = .5 * options.width * options.height;
      break;
    /* ... more code ... */
  }

  return area;
}

getArea('Triangle', { width: 100, height: 100 }); // 魔术字符串

例如上述代码,Triangle就是一个魔术字符串,It will appear many times inmore code部分,Form a strong coupling with the code.

常用的消除魔术字符串的方法,就是把它写成一个变量.

const shapeType = {
  triangle: 'Triangle'
};

function getArea(shape, options) {
  let area = 0;
  switch (shape) {
    case shapeType.triangle:
      area = .5 * options.width * options.height;
      break;
  }
  return area;
}

getArea(shapeType.triangle, { width: 100, height: 100 });

如果仔细分析,可以发现shapeType.triangle等于哪个值并不重要,只要确保不会跟其他shapeType属性的值冲突即可.因此,这里就很适合改用 Symbol 值.

const shapeType = {
  triangle: Symbol()
};

7、Symbol常用方法

Symbol.for(key)

  • 作用:使用给定的key搜索现有的symbol【key表示symbol中的description】
  • 返回值:如果找到,返回该symbol;否则将创建一个新的symbol,key作为description,添加到注册表中并返回.
  • 简述:用description找Symbol,找到就返回,找不到就创建一个新的Symbol.

Symbol.keyFor(symbol)

  • 作用:从symbol注册表中,返回指定symbol的description,没有则返回undefined.
  • 返回值:如果有description,返回;否则返回undefined.

注意:

  • 如果使用Symbol()定义的symbol,Will not be added to the registry;使用Symbol.for()定义的symbolWill be added to the registry.
  • Symbol.for(key)和Symbol.keyFor(sym)都是在SymbolThe registry to find.不会找到Symbol()定义的symbol

8、遍历对象中的Symbol

let symbol = Symbol("sym");
let obj = {
    name: "symbol_name",
    [symbol]: "唯一性"
};

// The basic attributes of access object
for (const key in obj) {
    console.log(key); // name
}
for (const key of Object.keys(obj)) {
    console.log(key); // name
}

// Access object of private property
for (const key of Object.getOwnPropertySymbols(obj)) {
    console.log(key); // Symbol(sym)
}

for (const key of Reflect.ownKeys(obj)) {
    // Access to all attributes of the object
    console.log(key); // name 、Symbol(sym)
}

注意:

  • Attributes of the object to use a variable's value,必须使用[变量名]
  • SymbolType as the object of private property,通过for/in、for/of无法遍历,必须使用Object.getOwnPropertySymbols(对象)或Reflect.ownKeys(对象)进行遍历

此外,Symbol还有11个ES6内置的 Symbol 值,指向语言内部使用的方法,Are interested, please go to the following reference the first link of learning.

学习参考:

copyright notice
author[Luo Li],Please bring the original link to reprint, thank you.
https://en.chowdera.com/2022/266/202209231010125134.html

Random recommended