普通视图
Code Review 惊魂:同事的“优雅”重构,差点让管理员全部掉线
React 渲染两次:是 Bug 还是 Feature?聊聊严格模式的“良苦用心”
BaseObject 及其子类的完整继承关系 ASCII 树
你真的懂递归吗?没那么复杂,但也没那么简单
从0-1封装一个React组件
脚本猫中的新建脚本:定时脚本、后台脚本、普通脚本,三个区别
涨见识了,Error.cause 让 JavaScript 错误调试更轻松
Ant Design Vue 日期选择器英文不变更中文问题
🌹🌹🌹bro,AntD 6.0.0 来了
Electron 第一步
从数字到版面:得物数据产品里数字格式化的那些事
Vue 跨组件通信底层:provide/inject 原理与实战指南
前端跨页面通讯终极指南①:postMessage 用法全解析
2025 年值得关注的 CSS 新属性与功能
ECMAScript 2025 正式发布:10 个让你眼前一亮的 JavaScript 新特性!
在数据录入、指标补录、表单填报场景中,SpreadJS 具备哪些优势和价值
JavaScript 中的 Symbol:特性与实战应用
JavaScript 中的 Symbol:特性与实战应用
在 JavaScript 的世界里,数据类型是构建一切的基础。ES6 的出现为我们带来了两种新的简单数据类型,其中之一就是 Symbol。本文将结合实例,详细解析 Symbol 的特性、用法及实际价值。
一、Symbol 是什么?数据类型的新成员
JavaScript 共有 8 种数据类型,可分为 "简单数据类型" 和 "复杂数据类型" 两大类:
-
复杂数据类型:仅
object一种 -
简单数据类型:
- 传统类型:
number、boolean、string、null、undefined - ES6 新增:
bigint(大数)、symbol(符号)
- 传统类型:
Symbol 的核心定义是:一种独一无二的值,它的出现主要是为了解决对象属性名冲突的问题。
二、Symbol 的声明方式
Symbol 通过Symbol()函数声明(注意:虽然使用函数形式,但它是简单数据类型,而非对象),语法如下:
// 基本声明
const sym = Symbol();
// 带描述符的声明(描述符仅用于标识,不影响唯一性)
const symWithDesc = Symbol('这是一个描述');
代码示例解析(symbol/1.js) :
// 声明两个Symbol类型变量
const id1 = Symbol();
console.log(typeof id1); // 输出:"symbol",证明是简单数据类型
const id2 = Symbol();
// 核心特性:独一无二,即使无参数,两个Symbol也不相等
console.log(id1 === id2); // 输出:false
从代码可见,即使两个 Symbol 变量没有任何参数,它们也绝对不相等,这是 Symbol 最核心的特性。
三、Symbol 作为对象的唯一键:解决命名冲突
在多人协作开发中,对象的动态特性可能导致属性名冲突(后定义的属性会覆盖先定义的)。而 Symbol 作为对象的键(key)时,能完美避免这个问题,因为它是独一无二的。
代码示例解析(symbol/2.js) :
// 两个描述符相同的Symbol,依然不相等
const s1 = Symbol('二哈');
const s2 = Symbol('二哈');
console.log(s1 === s2); // 输出:false
// 声明一个用于"秘密信息"的Symbol键
const secretKey = Symbol('secret');
console.log(secretKey, '//////'); // 输出:Symbol(secret) //////
// 演示Symbol作为对象键的优势
const a = "ecut";
const user = {
[secretKey]: '111222', // Symbol作为键,避免被意外覆盖
email: '123@qq.com',
name: '曹仁',
"a": 456, // 字符串键"a"
[a]: 123 // 变量a(值为"ecut")作为键,等价于"ecut":123
};
// 访问对象属性
console.log(user.ecut, user[a]); // 输出:123 123(两种方式访问同一个键)
// 普通字符串键可以被修改
user.email = 'ren@qq.com';
在上述代码中,secretKey作为 Symbol 键,即使其他开发者在对象中添加同名字符串键,也不会影响它的值,确保了数据的安全性。
四、Symbol 键的不可枚举性与访问方式
与普通字符串键不同,Symbol 作为对象的键时,不会被for...in循环枚举,也不会被Object.keys()等方法获取。这一特性让 Symbol 键适合存储 "私有" 或 "辅助" 信息。
若要访问对象中的 Symbol 键,需使用Object.getOwnPropertySymbols()方法,该方法会返回对象中所有 Symbol 键组成的数组。
代码示例解析 :
// 声明两个Symbol变量
const wes = Symbol('Wes');
const person = Symbol('Wes');
// console.log(wes === person); // 输出:false(即使描述相同也不相等)
// 定义包含Symbol键的对象
const classRoom = {
[Symbol('Mark')]: { grade: 50, gender: 'male' },
[Symbol('oliva')]: { grade: 80, gender: 'female' },
[Symbol('oliva')]: { grade: 85, gender: 'female' }, // 不会覆盖前一个oliva,因为是不同Symbol
"dl": ["张三", "李四"] // 普通字符串键
};
// 1. 测试for...in循环:仅能枚举字符串键
for (const person in classRoom) {
console.log(person, '////'); // 仅输出:dl ////
}
// 2. 获取所有Symbol键
const syms = Object.getOwnPropertySymbols(classRoom);
console.log(syms); // 输出:[Symbol(Mark), Symbol(oliva), Symbol(oliva)]
// 3. 访问Symbol键对应的值
const data = syms.map(sym => classRoom[sym]);
console.log(data);
// 输出:[
// { grade: 50, gender: 'male' },
// { grade: 80, gender: 'female' },
// { grade: 85, gender: 'female' }
// ]
代码中,classRoom对象包含 3 个 Symbol 键和 1 个字符串键。for...in循环仅能获取到字符串键dl,而Object.getOwnPropertySymbols()则能准确获取所有 Symbol 键,再通过映射即可访问对应的值。
五、总结
Symbol 作为 ES6 新增的简单数据类型,凭借 "独一无二" 和 "不可枚举" 的特性,在实际开发中有着重要作用:
- 作为对象键,避免多人协作时的命名冲突
- 存储 "私有" 信息,不被常规枚举方法获取
- 描述符仅用于标识,不影响其唯一性
掌握 Symbol 的用法,能让我们在处理对象属性时更加灵活、安全,尤其适合大型项目和多人协作场景。