网站栏目列表,项目网站建设业务分析,南宁做网约车哪个平台比较好,wordpress 学校模版JavaScript 中的 Symbol 特性详解
1. 什么是 Symbol#xff1f;
Symbol 是 ECMAScript 6 引入的一种新的原始数据类型#xff0c;表示唯一的值。它是 JavaScript 的第七种数据类型#xff08;前六种是#xff1a;undefined、null、布尔值、字符串、数值、对象#xff09…JavaScript 中的 Symbol 特性详解1. 什么是 SymbolSymbol 是 ECMAScript 6 引入的一种新的原始数据类型表示唯一的值。它是 JavaScript 的第七种数据类型前六种是undefined、null、布尔值、字符串、数值、对象。// 创建 Symbolletsym1Symbol();letsym2Symbol();console.log(sym1sym2);// false - 每个 Symbol 都是唯一的// 可以添加描述仅用于调试letsym3Symbol(description);letsym4Symbol(description);console.log(sym3sym4);// false - 即使描述相同Symbol 也不同2. 创建 Symbol 的方法2.1 基本创建方式// 直接创建constsymbol1Symbol();// 带描述创建constsymbol2Symbol(id);constsymbol3Symbol(id);// 使用 Symbol.for() 创建全局 Symbolconstsymbol4Symbol.for(globalKey);// 全局注册constsymbol5Symbol.for(globalKey);// 返回已存在的 Symbolconsole.log(symbol4symbol5);// true// Symbol.keyFor() 获取全局 Symbol 的键console.log(Symbol.keyFor(symbol4));// globalKeyconsole.log(Symbol.keyFor(symbol2));// undefined - 非全局 Symbol2.2 常用内置 Symbol// Symbol.iterator - 定义对象的默认迭代器constiterableObj{[Symbol.iterator]:function*(){yield1;yield2;yield3;}};// Symbol.toStringTag - 自定义 Object.prototype.toString() 的返回值classMyClass{get[Symbol.toStringTag](){returnMyClass;}}console.log(Object.prototype.toString.call(newMyClass()));// [object MyClass]// Symbol.hasInstance - 自定义 instanceof 操作符的行为classMyArray{static[Symbol.hasInstance](instance){returnArray.isArray(instance);}}console.log([]instanceofMyArray);// true3. Symbol 的主要特性3.1 唯一性constobj{};constkey1Symbol(key);constkey2Symbol(key);obj[key1]value1;obj[key2]value2;console.log(obj[key1]);// value1console.log(obj[key2]);// value2console.log(Object.keys(obj));// [] - Symbol 属性不会出现在常规遍历中3.2 不可枚举性默认constobj{regularProp:regular,[Symbol(symbolProp)]:symbol};// for...in 循环for(letkeyinobj){console.log(key);// 只输出 regularProp}// Object.keys()console.log(Object.keys(obj));// [regularProp]// Object.getOwnPropertyNames()console.log(Object.getOwnPropertyNames(obj));// [regularProp]// 获取 Symbol 属性constsymbolsObject.getOwnPropertySymbols(obj);console.log(symbols);// [Symbol(symbolProp)]3.3 用作对象属性的优势// 避免属性名冲突constuser{name:John,[Symbol(id)]:12345,[Symbol(id)]:67890// 不会覆盖前一个};// 模拟私有属性不是真正的私有但提供了命名空间的隔离constageSymbolSymbol(age);classPerson{constructor(name,age){this.namename;this[ageSymbol]age;}getAge(){returnthis[ageSymbol];}}constpersonnewPerson(Alice,30);console.log(person.name);// Aliceconsole.log(person.age);// undefinedconsole.log(person.getAge());// 304. Symbol 的实用场景4.1 实现常量// 传统方式 - 可能被意外修改constCOLOR_REDRED;constCOLOR_GREENGREEN;// Symbol 方式 - 确保唯一性constCOLOR_REDSymbol(RED);constCOLOR_GREENSymbol(GREEN);functiongetColor(color){switch(color){caseCOLOR_RED:return#ff0000;caseCOLOR_GREEN:return#00ff00;default:return#000000;}}4.2 定义对象元数据constCACHE_KEYSymbol(cache);functionwithCache(fn){returnfunction(...args){if(!this[CACHE_KEY]){this[CACHE_KEY]newMap();}constkeyJSON.stringify(args);if(this[CACHE_KEY].has(key)){returnthis[CACHE_KEY].get(key);}constresultfn.apply(this,args);this[CACHE_KEY].set(key,result);returnresult;};}classCalculator{withCacheheavyCalculation(x,y){console.log(Calculating...);returnx*y;}}4.3 定义协议接口// 自定义迭代协议classRange{constructor(start,end){this.startstart;this.endend;}[Symbol.iterator](){letcurrentthis.start;constendthis.end;return{next(){if(currentend){return{value:current,done:false};}return{done:true};}};}}constrangenewRange(1,5);console.log([...range]);// [1, 2, 3, 4, 5]5. Symbol 的 API 总结5.1 静态属性// 内置 SymbolSymbol.iterator Symbol.asyncIterator Symbol.match Symbol.replace Symbol.search Symbol.split Symbol.hasInstance Symbol.isConcatSpreadable Symbol.unscopables Symbol.species Symbol.toPrimitive Symbol.toStringTag5.2 静态方法// Symbol.for(key)constglobalSymSymbol.for(app.unique);// Symbol.keyFor(sym)constkeySymbol.keyFor(globalSym);// app.unique// Symbol.hasInstance// Symbol.isConcatSpreadable// 等其他内置 Symbol5.3 实例方法constsymSymbol(test);// toString()console.log(sym.toString());// Symbol(test)// valueOf()console.log(sym.valueOf()sym);// true// description (ES2019)console.log(sym.description);// test6. 注意事项6.1 类型转换constsymSymbol(test);// 不能转换为数字console.log(Number(sym));// TypeError// 可以转换为字符串console.log(String(sym));// Symbol(test)console.log(sym.toString());// Symbol(test)// 可以转换为布尔值console.log(Boolean(sym));// trueconsole.log(!sym);// false6.2 属性访问constobj{};constsymSymbol(key);obj[sym]value;// 正确的访问方式console.log(obj[sym]);// value// 错误的方式console.log(obj.sym);// undefined6.3 克隆和序列化constobj{regular:value,[Symbol(symbol)]:symbolValue};// JSON.stringify 会忽略 Symbol 属性console.log(JSON.stringify(obj));// {regular:value}// 扩展运算符会复制 Symbol 属性constcloned{...obj};console.log(Object.getOwnPropertySymbols(cloned).length);// 17. 实际应用示例7.1 实现单例模式constsingletonKeySymbol.for(app.singleton);classSingleton{constructor(){constinstancethis.constructor[singletonKey];if(instance){returninstance;}this.constructor[singletonKey]this;}}consts1newSingleton();consts2newSingleton();console.log(s1s2);// true7.2 元编程// 使用 Symbol.toPrimitive 控制对象到原始值的转换constobj{value:10,[Symbol.toPrimitive](hint){if(hintnumber){returnthis.value;}if(hintstring){returnValue:${this.value};}returnthis.value;}};console.log(Number(obj));// 10console.log(String(obj));// Value: 10console.log(obj5);// 15总结Symbol 的主要特点唯一性每个 Symbol 都是唯一的避免命名冲突隐私性Symbol 属性默认不可枚举提供一定程度的属性隐藏协议性内置 Symbol 用于定义和扩展 JavaScript 对象的行为不可变性Symbol 值创建后不可修改Symbol 是现代 JavaScript 编程中重要的元编程工具特别适用于定义对象内部方法如迭代器创建不会冲突的属性名实现自定义类型转换定义框架或库的内部协议正确使用 Symbol 可以提高代码的可维护性和健壮性避免属性名冲突并实现更优雅的元编程模式。