Symbol是什么?
ES6引入了一种全新的原始数据类型------Symbol ,它是JS的第7种类型(前6种:undefined
、null
、Boolean
、String
、Number
、Object
)。它的核心特点是:每个Symbol值都是独一无二的!🎭
创建Symbol
通过Symbol()
函数生成,不能用new
(因为它不是对象):
javascript
let s = Symbol();
console.log(typeof s); // "symbol"
可以传参作为描述(仅用于调试,不影响唯一性):
javascript
let s1 = Symbol('我是s1');
let s2 = Symbol('我是s2');
console.log(s1.toString()); // "Symbol(我是s1)"
console.log(s2.toString()); // "Symbol(我是s2)"
⚠️ 注意:相同参数的Symbol不相等!
javascript
let s3 = Symbol('desc');
let s4 = Symbol('desc');
console.log(s3 === s4); // false
Symbol的经典应用场景
作为对象属性名
用Symbol作属性名,完全杜绝重名问题,适合多模块协作!
javascript
const PRO_KEY = Symbol();
let obj = {
[PRO_KEY]: '私有属性值'
};
console.log(obj[PRO_KEY]); // "私有属性值"
❌ 错误用法:用点运算符访问Symbol属性!
javascript
obj.PRO_KEY = 'Hello'; // 这只是普通属性,和Symbol无关!
console.log(obj[PRO_KEY]); // "私有属性值"
消除魔术字符串
魔术字符串 :指的是在代码中多次直接使用 的字符串或数值,这些值与代码逻辑强耦合(逻辑和具体字符串绑定,复用性差),像"魔法"一样难以维护和修改。用Symbol代替,代码更健壮!
原始代码(魔术字符串问题):
javascript
function getArea(shape) {
switch(shape) {
case 'Triangle': /* 计算三角形 */ break;
case 'Square': /* 计算正方形 */ break;
}
}
getArea('Triangle'); // 'Triangle'是魔术字符串
改进后(用Symbol):
javascript
const shapeType = {
triangle: Symbol('Triangle'),
square: Symbol('Square')
};
function getArea(shape) {
switch(shape) {
case shapeType.triangle: /* ... */ break;
case shapeType.square: /* ... */ break;
}
}
getArea(shapeType.triangle); // 清晰且唯一!
Symbol的"隐藏属性"特性
Symbol属性不会被常规方法遍历到,适合定义"私有"属性:
javascript
const obj = {
[Symbol('secret')]: '隐藏值',
name: '小明'
};
// 以下方法都拿不到Symbol属性!
console.log(Object.keys(obj)); // ["name"]
console.log(Object.getOwnPropertyNames(obj)); // ["name"]
// 只能用这个方法获取Symbol属性:
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(secret)]
Symbol的"全局注册表"
通过Symbol.for()
可以创建全局共享的Symbol:
javascript
const s1 = Symbol.for('global');
const s2 = Symbol.for('global');
console.log(s1 === s2); // true
// 获取已注册Symbol的key:
console.log(Symbol.keyFor(s1)); // "global"
内置Symbol值(装逼必备🌟)
ES6内置了一些Symbol值,用于控制语言内部行为:
- Symbol.iterator:定义对象的迭代器
- Symbol.toStringTag :自定义
Object.prototype.toString
的输出 - Symbol.hasInstance :修改
instanceof
的行为
javascript
class MyClass {
static [Symbol.hasInstance](obj) {
return Array.isArray(obj);
}
}
console.log([] instanceof MyClass); // true (颠覆三观!)
写在最后
- Symbol的定位:唯一值、防冲突、隐藏属性。
- 适用场景:常量定义、私有属性、消除魔术字符串。
- 避坑指南 :不能用
new
、点运算符无效、遍历需特殊方法。
💪 学习感悟:自学到Symbol时,总觉得它"花里胡哨",直到在项目里用它解决了命名冲突,真香!