js基石之Symbol值

js基石之数据类型一:类型分类&区别
js基石之数据类型二:类型判断
js基石之数据类型三:类型转换
js基石之Number:本质
js基石之Number:应用(数字运算,数字&字符串转换,不同进制表示&相互转换)
js基石之字符: ASCII,GBK,Unicode,utf-32,utf-16,utf-8,encodeuri,encodeuricomponent,base64
js基石之Symbol值

先有问题再有答案

  1. Symbol是什么
  2. Symbol和其他数据类型有什么关系?
  3. Symbol有什么特性
  4. 有哪些应用场景
  5. 你都掌握了哪些有用的Symbol值?

Symbol是什么

symbol是一种基本数据类型, 通过Symbol函数生成symbol值,symbol值都是唯一的。一个 symbol 值能作为对象属性的标识符;这是该数据类型仅有的目的

一个原始值

javascript 复制代码
const s = Symbol('a')
typeof s // 'symbol'

Symbol函数

Symbol作为函数的唯一作用就是生成symbol值。

Symbol对象

  • 对象属性:Symbol.iterator,Symbol.toPrimitive,Symbol.toStringTag...
  • 原型方法:Symbol.prototype原型定义了toString,valueOf方法 同时Symbol原型链上也有Function.prototype&Object.prototype。
  • 静态方法:Symbol.for,Symbol.keyFor

Symbol&其他类型

Number: 不能相互转换

javascript 复制代码
let sym = Symbol('1'); 

let num = sym + 1; // Uncaught TypeError: Cannot convert a Symbol value to a number

Number(sym) // Uncaught TypeError: Cannot convert a Symbol value to a number

parseInt(sym) // Uncaught TypeError: Cannot convert a Symbol value to a number

String:不能隐式转换

ini 复制代码
let sym = Symbol('test'); 
let str = sym + 'hello'; // Cannot convert a Symbol value to a string

可以显式转换

ini 复制代码
let sym = Symbol('test'); 

let str1 = sym.toString(); // 使用 Symbol.prototype.toString 方法进行转换 
// 返回:"Symbol(test)" 

let str2 = String(sym); // 使用 String 函数进行转换  
// 返回:"Symbol(test)"

Boolean

所有的 Symbol 类型的值在转换为布尔值时都是 true,无论它们的描述是什么

ini 复制代码
let sym1 = Symbol('test'); 
let bool1 = !!sym1; // 返回:true 

let sym2 = Symbol(); 
let bool2 = !!sym2; // 返回:true

let bool = Boolean(sym2); // 返回:true

包装类

Symbol函数不能通过new调用,没有对应的包装类 es2015之后新增的基本数据类型(BigInt)都不能通过new调用,这是JavaScript 语言的设计决定。

虽然引擎提供了自动装箱和拆箱功能,但是Symbol&BigInt两种类型 不适合当做对象使用。

Symbol的特性

1:symbol没有字面量形式 只能通过Symbol函数生成。

ini 复制代码
let sym1 = Symbol('test'); 

2:symbol表示唯一值

每个 Symbol 值都是唯一的,即使你创建了两个具有相同描述的 Symbol 值,它们也是不相等的。这使得 Symbol 值成为了创建对象的唯一属性键的理想选择,可以避免属性名的冲突。

ini 复制代码
let sym1 = Symbol('test'); 
let sym2 = Symbol('test'); 
sym1 === sym2 // false

3:不可枚举

Symbol 值作为对象的属性键时,这个属性不会出现在常规的遍历操作中(如 for...in 循环、Object.keys()、JSON.stringify() 等),只能通过 Object.getOwnPropertySymbols() 或 Reflect.ownKeys() 来获取。

ini 复制代码
let sym = Symbol('test'); 
let obj = { [sym]: 'value', prop: 'value' }; 
console.log(Object.keys(obj)); // 输出:['prop'] console.log(Object.getOwnPropertySymbols(obj)); // 输出:[Symbol(test)]

应用场景

创建唯一的属性键:

由于每个 Symbol 都是唯一的,所以可以用它来创建唯一的属性键,避免属性名的冲突。

ini 复制代码
let id = Symbol('id'); 
let user = { 
   [id]: 1, 
   name: 'John', 
   age: 30 
};

内置的Symbol值(常用的)

Symbol.iterator:迭代器

javascript 复制代码
let iterable = {
  [Symbol.iterator]() {
    let i = 0;
    return {
      next() {
        if (i < 5) {
          return { value: i++, done: false };
        } else {
          return { value: undefined, done: true };
        }
      }
    };
  }
};

for (let value of iterable) {
  console.log(value); // 输出:0, 1, 2, 3, 4
}

Symbol.toPrimitive:类型转换

csharp 复制代码
const obj = {
    value: 1,
    [Symbol.toPrimitive](){
        return 10
    },
};

obj + 1 // 11
obj + '1' // '101'
'1' + obj // 110

Symbol.toStringTag:类型判断

javascript 复制代码
Number.prototype[Symbol.toStringTag] = 'String';
let a = 12;
Object.prototype.toString.call(a)  // '[object String]'成功的将数字改变为字符串

补充

symbol具有唯一性。还有哪些方式可以表示唯一性?

  1. 时间戳
ini 复制代码
let timestamp = Date.now();
  1. 使用 Math.random():
    Math.random() 函数返回一个介于 0(包含)和 1(不包含)之间的随机数,所以你可以用它来生成一个几乎唯一的值。但是,Math.random() 函数的结果是不可预测的,所以它不能保证生成的值一定是唯一的。
vbscript 复制代码
Math.random().toString(36).substring(2)
  1. uuid
javascript 复制代码
npm install uuid
import { v4 as uuidv4 } from 'uuid';
uuidv4(); // ⇨ '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'

参考

  1. es6_symbol
  2. mdn_Symbol
相关推荐
undefined&&懒洋洋4 分钟前
Web和UE5像素流送、通信教程
前端·ue5
大前端爱好者2 小时前
React 19 新特性详解
前端
随云6322 小时前
WebGL编程指南之着色器语言GLSL ES(入门GLSL ES这篇就够了)
前端·webgl
随云6322 小时前
WebGL编程指南之进入三维世界
前端·webgl
J老熊2 小时前
Spring Cloud Netflix Eureka 注册中心讲解和案例示范
java·后端·spring·spring cloud·面试·eureka·系统架构
我爱学Python!2 小时前
面试问我LLM中的RAG,秒过!!!
人工智能·面试·llm·prompt·ai大模型·rag·大模型应用
OLDERHARD3 小时前
Java - LeetCode面试经典150题 - 矩阵 (四)
java·leetcode·面试
寻找09之夏3 小时前
【Vue3实战】:用导航守卫拦截未保存的编辑,提升用户体验
前端·vue.js
非著名架构师3 小时前
js混淆的方式方法
开发语言·javascript·ecmascript
银氨溶液4 小时前
MySql数据引擎InnoDB引起的锁问题
数据库·mysql·面试·求职