当前位置: 首页 > article >正文

JS中的【Symbol】全面讲解

1. 什么是 Symbol?

Symbol 是 ES6 引入的一种新的原始数据类型(Primitive Data Type)。与 stringnumberbooleannullundefined 一样,Symbol 是不可变的原始值。Symbol 的特殊之处在于它是唯一的,即使两个 Symbol 的描述相同,它们的值也不相等。

2. Symbol 的创建

Symbol 通过 Symbol() 函数创建,可以接受一个可选的字符串参数作为描述(description),用于调试或日志记录,但不影响 Symbol 的唯一性。

let sym1 = Symbol();
let sym2 = Symbol('foo');
let sym3 = Symbol('foo');

console.log(sym2 === sym3); // false
3. Symbol 的用途
  • 作为对象属性的键(Key): Symbol 最常见的用途之一是用作对象的属性键。由于每个 Symbol 都是唯一的,因此它可以确保属性不被意外覆盖或冲突。
let mySymbol = Symbol('myKey');
let obj = {};

obj[mySymbol] = 'value';
console.log(obj[mySymbol]); // 'value'
  • 防止对象属性名冲突: 使用 Symbol 作为对象属性名可以避免在大型代码库或库之间发生属性名冲突。

  • 实现迭代器(Iterators): Symbol.iterator 是内置的 Symbol,用于定义对象的默认迭代器。当对象使用 for...of 循环遍历时会调用这个方法。

let iterable = {
  [Symbol.iterator]() {
    let step = 0;
    return {
      next() {
        step++;
        if (step <= 5) {
          return { value: step, done: false };
        }
        return { value: undefined, done: true };
      }
    };
  }
};

for (let value of iterable) {
  console.log(value); // 1, 2, 3, 4, 5
}
  • 元编程和反射(Reflection): Symbol 还可以用来定义对象行为的某些方面,比如 Symbol.toPrimitiveSymbol.toStringTag 等,这些 Symbol 可以自定义对象的原生行为。
let obj = {
  [Symbol.toPrimitive](hint) {
    if (hint === 'number') {
      return 10;
    }
    return null;
  }
};

console.log(+obj); // 10
4. 内置 Symbol

JavaScript 提供了一些内置的 Symbol,用于语言的内部机制。常见的内置 Symbol 包括:

  • Symbol.iterator:定义对象的默认迭代器。
  • Symbol.toPrimitive:对象转换为原始类型时调用的函数。
  • Symbol.toStringTag:修改 Object.prototype.toString() 的返回值。
  • Symbol.hasInstance:自定义 instanceof 操作符的行为。
  • Symbol.isConcatSpreadable:自定义数组 concat 方法是否展开对象。
class MyArray extends Array {
  static get [Symbol.species]() {
    return Array;
  }
}

let myArray = new MyArray(1, 2, 3);
let mappedArray = myArray.map(x => x * x);

console.log(mappedArray instanceof MyArray); // false
console.log(mappedArray instanceof Array);   // true
5. Symbol 的局限性
  • Symbol 无法被隐式转换为字符串或数字:使用 Symbol 作为字符串连接或数字运算时会抛出错误。这是为了防止意外的类型转换。
let sym = Symbol('foo');
console.log('Symbol is ' + sym); // TypeError: Cannot convert a Symbol value to a string
  • Symbol 的枚举性:使用 for...inObject.keys() 遍历对象时,Symbol 属性是不可枚举的,但可以使用 Object.getOwnPropertySymbols() 来获取对象的 Symbol 属性。
let obj = {
  [Symbol('key')]: 'value'
};

console.log(Object.keys(obj)); // []
console.log(Object.getOwnPropertySymbols(obj)); // [ Symbol(key) ]
  • Global Symbol 注册表:通过 Symbol.for()Symbol.keyFor() 可以使用全局的 Symbol 注册表,这允许你跨文件或模块共享 Symbol。
let globalSym = Symbol.for('globalKey');
let globalSym2 = Symbol.for('globalKey');

console.log(globalSym === globalSym2); // true
console.log(Symbol.keyFor(globalSym)); // 'globalKey'
6. Symbol 的实际应用场景
  • 框架和库中避免命名冲突: 当开发公共库或框架时,可以使用 Symbol 作为内部属性键,避免用户代码中的命名冲突。
  • 实现私有属性: 尽管 Symbol 不是完全私有的,但它可以作为一种模拟私有属性的手段,避免直接通过常规方法访问这些属性。
  • 自定义对象行为: 使用内置 Symbol 可以让对象表现出更符合预期的行为,如自定义对象的字符串表示、数值转换等。

总结来说,Symbol 是 JavaScript 中强大且灵活的工具,提供了许多高级功能,如安全的对象属性定义和元编程能力。掌握 Symbol 有助于编写更加健壮和可扩展的代码。


http://www.kler.cn/a/291936.html

相关文章:

  • 传奇996_23——杀怪掉落,自动捡取,捡取动画
  • 前端Javascript、Vue、CSS等场景面试题目(二)
  • AntFlow:一款高效灵活的开源工作流引擎
  • 使用 Grafana api 查询 Datasource 数据
  • MySQL数据库:SQL语言入门 【3】(学习笔记)
  • 大三学生实习面试经历(1)
  • 启动spring boot项目时,第三方jar包扫描不到的问题。
  • 编程效率革命:智能工具与自动化脚本的完美结合
  • 144. 腾讯云Redis数据库
  • MOM成功实施分享(三)数字化项目落地蓝图经验分享
  • 2024 高教社杯 数学建模国赛 (B题)深度剖析|生产过程中的决策问题|数学建模完整代码+建模过程全解全析
  • echarts多个环形图
  • Linux 进程与线程相关函数及进程间通信方法
  • 基于微信小程序的挂号管理系统-web管理端
  • 酒店预约小程序搭建,让酒店更加智能化
  • SQLite 创建表:一场数据库里的“造物运动”
  • controlnet reference only
  • 微信小程序:如何在实现页面之间的返回
  • 一篇文章带你走进测试工程师的世界
  • C++ 中的const关键字
  • 前端框架vue3中的条件渲染(v-show,v-if,v-else-if,v-else)
  • Linux——网络(5)
  • 9.3 k8s介绍
  • 【高等代数笔记】(14-17)N阶行列式
  • Spring启动流程
  • 【C-实践】一对一的网络通信(tcp+select)