首页 > 其他分享 >JS数据类型 之 Symbol详解

JS数据类型 之 Symbol详解

时间:2022-09-23 09:36:19浏览次数:76  
标签:console log symbol 数据类型 JS let key Symbol

1、Symbol概述

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

它属于JavaScript语言的原生数据类型之一,其他数据类型是:undefined、null、Boolean、String、Number、Bigint、Object。

使用场景:

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

比如,你使用了一个他人提供的对象,你想为这个对象添加新的方法(mixin模式),这个时候新方法的名字就有可能和现有的方法重名,这个时候就可以使用Symbol,来防止你新追加的方法重名。


2、Symbol的特性

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

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

注意:Symbol()函数之前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,而不是对象。另外,由于Symbol值不是对象,所以也不能添加属性。基本上它就是一种类似字符串的数据类型


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 实例的描述。

这主要是为了在控制台显示,或者转为字符串的时候,比较容易区分。

注意: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

当Symbol函数的参数是一个对象时,会自动调用对象中的toString方法,转成字符串之后,再把这个字符串作为参数去执行。

Symbol可以转成字符串、布尔值,不能转成数字,也不能和其他类型的值进行运算。


3、Symbol.prototype.description

ES2019提供了一个Symbol值的实例属性description,可以直接返回Symbol值的描述。

let s = Symbol('my symbol')

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

4、Symbol作为对象属性名

由于每一个 Symbol 值都是不相等的,这意味着只要 Symbol 值作为标识符,用于对象的属性名,就能保证不会出现同名的属性。

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、消除魔术字符串

魔术字符串指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。风格良好的代码,应该尽量消除魔术字符串,改由含义清晰的变量代替。

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就是一个魔术字符串,它会多次出现在more 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,则不会添加到注册表中;使用Symbol.for()定义的symbol则会添加到注册表中。
  • Symbol.for(key)和Symbol.keyFor(sym)都是在Symbol注册表中进行查找。不会找到Symbol()定义的symbol

8、遍历对象中的Symbol

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

// 访问对象的基本属性
for (const key in obj) {
    console.log(key); // name
}
for (const key of Object.keys(obj)) {
    console.log(key); // name
}

// 访问对象中的私有属性
for (const key of Object.getOwnPropertySymbols(obj)) {
    console.log(key); // Symbol(sym)
}

for (const key of Reflect.ownKeys(obj)) {
    // 访问对象的所有属性
    console.log(key); // name 、Symbol(sym)
}

注意:

  • 对象的属性要使用变量值,必须使用[变量名]
  • Symbol类型作为对象的私有属性,通过for/in、for/of无法遍历,必须使用Object.getOwnPropertySymbols(对象)或Reflect.ownKeys(对象)进行遍历

学习参考:

标签:console,log,symbol,数据类型,JS,let,key,Symbol
From: https://www.cnblogs.com/luckest/p/16721576.html

相关文章

  • js修改网址URL参数的方法
    js修改URL参数,修改后可刷新页面也可以不刷新页面//paramName=参数名称,replaceWith=参数值,isRefresh=是否刷新(0不刷新,1刷新)//使用方法:replaceParamVal("userId",......
  • rxjs 在 react 下的应用
    设置一个subject,然后在组件内定义一个subscription想要发送事件就用subject.next订阅就赋值subject.asObservable().subscribe()直接看代码constsubject=ne......
  • JS 使用sessionStorage存取对象时显示[object object]的解决
    使用sessionStorage进行数据存取,如果数据是对象,则提取时为[objectobject],基于此问题,解决方法如下: 保存数据时window.sessionStorage.setItem("key",JSON.stringify(v......
  • js ArrayBufferView & TypeArray All In One
    jsArrayBufferView&TypeArrayAllInOne//✅>1000002**64;18446744073709552000//✅>1000002**32;4294967296//❌太小了<1000002**16;65536/......
  • js Object key All In One
    jsObjectkeyAllInOne//字面符号/初始化符号obj={};obj[0]='a';//'a'obj;//{0:'a'}0:"a"[[Prototype]]:Objectobj[false]=true;//trueobj......
  • JS 闭包
    闭包(closure)是Javascript语言的一个难点,也是它的特色。闭包的作用:通过一系方法,将函数内部的变量(局部变量)转化为全局变量。要理解闭包,首先必须理解Javascript特殊的变......
  • JSON和JavaScript自定义对象
    JavaScript自定义对象:var对象名称={属性名称1:属性值1,属性名称2:属性值2,...,函数名称:function(形参列表){},...}; 访问对象:对象名称.属性名称......
  • js实现数组内相邻元素上移,下移
    上移、下移/**   *移动切换位置   *@param{Array}arr数据源   *@param{Number}index序号   *@param{String}type上移下移......
  • JS注意事项 && 代码调试
    JavaScript识别七种基本(不可变)数据类型:Boolean、Null、Undefined、Number、String、Symbol(ES6新增)和BigInt(ES2020新增),以及一种可变项类型:Object。注意,在JavaScript中,数组严......
  • nodejs 安装多版本 版本切换
          有时候需要运行不同的项目,node版本不一致会导致不少问题,特别是最新版本对应的一些插件,由于语法等原因导致不一定兼容低版本,这样运行低版本环境的项目的时候很......