网站首页 > 技术文章 正文
在JavaScript中,Symbol就像这个二维码——它是ES6引入的第七种原始类型,能创建完全唯一的标识。即使看起来相同的两个Symbol,本质上也是不同的:
const key1 = Symbol('订单号');
const key2 = Symbol('订单号');
console.log(key1 === key2); // false → 就像扫描不同的二维码
实战场景:Symbol的正确打开方式
1. 防止属性名重名
当扩展第三方库的对象时,Symbol能避免属性覆盖:
// 第三方库的代码
const utils = {
version: '1.0'
};
// 我们的扩展代码
const VERSION = Symbol('版本标识');
utils[VERSION] = '2.0';
console.log(utils.version); // '1.0' → 原属性不受影响
console.log(utils[VERSION]); // '2.0' → 新属性安全存放
这就好像贴上特殊标签,既不会拿错,也不会影响别人。
2. 实现“软私有”属性
虽然JavaScript没有真正的私有属性,但Symbol可以模拟:
const User = (() => {
const _password = Symbol('密码');
return class {
constructor(name, pwd) {
this.name = name;
this[_password] = pwd; // 外部无法直接访问
}
checkPassword(pwd) {
return this[_password] === pwd;
}
};
})();
const user = new User('Alice', '123456');
console.log(user[_password]); // 报错 → 类似保险箱密码
console.log(user.checkPassword('123456')); // true
3. 定义协议行为
内置Symbol值可以控制对象的核心功能:
class MyList {
constructor(items) {
this.items = items;
}
// 自定义迭代规则
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
return index < this.items.length
? { value: this.items[index++], done: false }
: { done: true };
}
};
}
}
const list = new MyList(['A', 'B', 'C']);
// 支持for...of遍历
for (const item of list) {
console.log(item); // A → B → C
}
这相当于给对象安装“驱动程序”,让它们支持标准接口(如迭代器、正则表达式匹配等)。
来点骚操作
1. 全局Symbol注册表
通过Symbol.for()实现跨模块共享:
// moduleA.js
const GLOBAL_KEY = Symbol.for('APP_CONFIG');
// moduleB.js
const configKey = Symbol.for('APP_CONFIG');
console.log(configKey === GLOBAL_KEY); // true → 全局唯一
2. 规避隐式类型转换
对象转原始值时,用Symbol.toPrimitive控制:
const account = {
balance: 100,
[Symbol.toPrimitive](hint) {
return hint === 'string' ? `余额:$
{this.balance}` : this.balance;
}
};
console.log(account + 50); // 150 → 数值计算
console.log(`${account}`); // "余额:$100" → 字符串场景
3. 标记特殊对象
React等库用Symbol标记组件类型:
// 类似React内部实现
const REACT_ELEMENT = Symbol.for('react.element');
function createElement(type, props) {
return {
$typeof: REACT_ELEMENT, // 防XSS的安全标记
type,
props
};
}
4. 替代常量枚举
避免魔法字符串:
// 传统方式(易冲突)
const STATUS = {
PENDING: 'PENDING',
SUCCESS: 'SUCCESS'
};
// Symbol方案
const STATUS = {
PENDING: Symbol('pending'),
SUCCESS: Symbol('success')
};
if (status === STATUS.PENDING) { ... }
5. 元编程标记
通过Symbol.toStringTag自定义对象描述:
class MyClass {
get [Symbol.toStringTag]() {
return 'MyCustomClass';
}
}
console.log(new MyClass().toString()); // [object MyCustomClass]
注意点:
- 无法被常规遍历
Symbol属性不会被for...in、Object.keys()枚举,需要Object.getOwnPropertySymbols()单独获取。 - JSON序列化问题
Symbol属性会被JSON.stringify()忽略,重要数据需额外处理。 - 慎用全局注册
Symbol.for()可能引发命名冲突,建议添加前缀如Symbol.for('MyApp:key')。 - 类型判断陷阱
typeof Symbol()返回'symbol',但instanceof检测无效,需用Object.prototype.toString.call()。
猜你喜欢
- 2024-09-12 前端大牛如何打好基础:常用Web前端技术总结
- 2024-09-12 web前端是什么?需要掌握什么技术?
- 2024-09-12 前端开发技术演进与专业成长
- 2024-09-12 技术干货:那些年我追过的前端技术
- 2024-09-12 前端代码的整洁之道 | 技术头条
- 2024-09-12 前端程序员的整体技术水平偏低吗?
- 2024-09-12 前端世界起争端,你是现代 Web 技术体系的坚定捍卫者吗?
- 2024-09-12 你知道那些大厂的前端都在用什么技术吗?#干货分享
- 2024-09-12 5个可以快速成为一名优秀的前端程序员秘诀,你用了吗?
- 2024-09-12 2023前端技术及开源发展研究报告|附下载
你 发表评论:
欢迎- 06-24发现一款开源宝藏级工作流低代码快速开发平台
- 06-24程序员危险了,这是一个 无代码平台+AI+code做项目的案例
- 06-24一款全新的工作流,低代码快速开发平台
- 06-24如何用好AI,改造自己的设计工作流?
- 06-24濮阳网站开发(濮阳网站建设)
- 06-24AI 如何重塑前端开发,我们该如何适应
- 06-24应届生靠这个Java简历模板拿下了5个offer
- 06-24服务端性能测试实战3-性能测试脚本开发
- 566℃Oracle分析函数之Lag和Lead()使用
- 565℃几个Oracle空值处理函数 oracle处理null值的函数
- 550℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 545℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 543℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 536℃【数据统计分析】详解Oracle分组函数之CUBE
- 526℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 519℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端富文本编辑器 (47)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle的函数 (57)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)