ES6 Symbol如何方便你接手离职同事的代码

如何接手离职同事的代码,ES6 Symbol,你值得了解

一.简单介绍一下 Symbol 类型

  1. 首先它是一种基本类型,像 string,bigInt 这些数据类型,没有方法,也不能 new,声明方法 const s1 = Symbol("desc")和其他基本类型相似 。
  2. 其次它的返回值是唯一且不可变的原始值,猜测在 V8 引擎中原理可能是由一个自增 symbol 链表或哈希实现。

二.代码实际中理解

一是用于做对象的键名,使得键名独一无二,这就是我为啥说 symbol 有利于接手离职同事的代码。

ini 复制代码
​
​
//现在我需要添加一下新的成员变量age存储age信息,你也不知道原来有木有这个变量。
const age = Symbol("age");
//这样声明的age变量一定不会覆盖本来成员变量
user[age] = 18;
// 我们可以在不影响原来数据结构下新增成员变量通过obj[age]访问
console.log(user.name, user[ID], user[age]);
​
csharp 复制代码
const user = {
  name: "Alice",
  [ID]: 123, //[]的意思是取值
  /*
  ·
  ·很多成员变量,而且变量名抽象
  ·
  ·
  */
};

假如这个对象成员很多,我想加一个age,但是懒得看原来的代码,可能因为原来的代码根本不知道变量的含义,前同事命名方式太抽象。

我们可以这样做

ini 复制代码
//现在我需要添加一下新的成员变量age存储age信息,你也不知道原来有木有这个变量。
const age = Symbol("age");
user[age] = 18;
// 我们可以在不影响原来数据结构下新增成员变量通过obj[age]访问

你可能会想到你的离职同事之前也和你一样写方式的,你不就炸了吗?

不用担心,并不会,其实这样添加的age变量一定不会覆盖本来成员变量。

它的返回值通过js机制和v8引擎的某种实现有关,前面也提了可能就是用递增链表或者哈希实现的。

javascript 复制代码
console.log( Symbol("age") === Symbol("age")) //  输出 false 
console.log( Symbol() === Symbol() ) //  可以不传description参数 一样 输出 false 

哎,这时候可能会有疑问,那我就要创建可复用的Symbol,怎么弄呢?

用Symbol.for('key')方法就行了,代码如下:

ini 复制代码
const s1 = Symbol.for('shared');
const s2 = Symbol.for('shared');
console.log(s1 === s2); // 这个时候就是true啦,不过感觉没啥用

另外Symbol 作为对象的键时不可枚举,可以避免外部直接修改状态。

补充一点Symbol 作为对象的键时不可枚举是什么意思呢?

就是说在用for,Obj.key()方式遍历时,用Symbol 作为对象的键不能被访问到。

那你会有疑问了,那我就要访问咋办?

用这个方法这个 Object.getOwnPropertySymbols(obj) 方法就可以了

请看代码:

ini 复制代码
​
const user = {
  name: "Alice",
  [ID]: 123, //[]的意思是取值
};
const age = Symbol("age");
user[age] = 18;
for (let i in user) {
  console.log(i); // 输出 name
}
Object.getOwnPropertyNames(user) // [name]
Object.getOwnPropertySymbols(user) // [Symbol(id),Symbol(age)]

有人问看不懂怎么办?我只能说懂得都懂,不懂你问ai就行了,因为作者也不太懂

二是用来做对象的值,实现类型c++中的有的而js没有枚举类型

比如我们来写一个订单订单的状态:

javascript 复制代码
// orderStatus.js
const ORDER_STATUS = {
  PENDING: Symbol("pending"), // 待支付
  PAID: Symbol("paid"), // 已支付
  SHIPPED: Symbol("shipped"), // 已发货
  COMPLETED: Symbol("completed"), // 已完成
  CANCELLED: Symbol("cancelled"), // 已取消
};
module.exports = ORDER_STATUS;

然后再来写订单的状态变化:

javascript 复制代码
​
// orderService.js
const STATUS = require("./orderStatus");
​
function updateOrderStatus(currentStatus, newStatus) {
  // 安全校验:确保新状态是有效的 Symbol 值
  if (!Object.values(STATUS).includes(newStatus)) {
    throw new Error("Invalid order status 无效的订单状态");
  }
​
  // 仅允许合法的状态转换(示例逻辑)
  if (currentStatus === STATUS.PAID && newStatus !== STATUS.SHIPPED) {
    throw new Error(
      "Paid order must transition to shipped  已付订单必须过渡到已付订单"
    );
  }
​
  // 更新状态...
  console.log(
    `Order status updated to:订单状态更新为: ${newStatus.description}`
  );
}
// 调用示例
updateOrderStatus(STATUS.PENDING, STATUS.PAID); // 合法操作
updateOrderStatus(STATUS.PAID, "invalid_status"); // 抛出异常(字符串无法通过校验)
​

这样可以防止字符串误写影响,像这样:updateStatus("paied")写错 。

三、总结

Symbol是一个es6的基本数据类型,为中大型项目而生,其实有关它的用法还很丰富,特别是访问方法那一块。这里推荐es6大佬阮一峰的讲解Symbol - ECMAScript 6入门

相关推荐
培根芝士17 分钟前
使用 Canvas 替代 <video> 标签加载并渲染视频
前端·javascript·音视频
德育处主任Pro1 小时前
p5.js 三角形triangle的用法
开发语言·javascript·ecmascript
持续前行1 小时前
vue3 : 导出pdf , 除iframe之外 ,还有其他内容一并导出方式
前端·javascript·vue.js
SenLinMu1 小时前
navigator.clipboard.writeText(text) 这段js在本地执行正常,但是在服务器执行失败时为什么?
javascript
BugCollect1 小时前
Lodash常用方法
前端·javascript
CAD老兵2 小时前
解锁 JavaScript 模块的秘密:ES6模块内部结构详解
前端·javascript
gnip2 小时前
nrm
前端·javascript
天天码行空2 小时前
Radash: 新一代前端工具库平替Lodash库
前端·javascript·github
gnip2 小时前
nvm
前端·javascript
GISer_Jing2 小时前
Flex布局面试常考的场景题目
前端·javascript·面试