我的编程空间,编程开发者的网络收藏夹
学习永远不晚

vscode工具函数Symbol如何使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

vscode工具函数Symbol如何使用

这篇文章主要介绍“vscode工具函数Symbol如何使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“vscode工具函数Symbol如何使用”文章能帮助大家解决问题。

    什么是Symbol?

    符号(Symbol)是JavaScript中的一个原始数据类型,是ECMAScript 6标准引入的新特性。符号是一种类似于字符串的数据类型,但与字符串不同的是,符号是唯一的并且不可变的。

    Symbol的定义方法如下:

    const mySymbol = Symbol('my symbol');

    每次调用Symbol创建的值都是唯一的,即使对同一个参数调用两遍Symbol它们的值还是不一样的:

    Symbol("foo") === Symbol("foo"); // false

    js的第六种基本数据类型

    Symbol出现之前,Javascript已经有五种内置的基本数据类型:

    • 布尔值(Boolean):表示真或假,只有两个取值:true和false。

    • 数字(Number):表示整数或浮点数,可以使用十进制、十六进制、八进制、科学计数法等多种表示方式。

    • 字符串(String):表示文本字符串,可以使用单引号、双引号、反引号等方式表示。

    • 空值(Null):表示一个空值或不存在的对象。

    • 未定义(Undefined):表示一个未定义的值或未声明的变量。

    Symbol则作为第六种基本数据类型加入到语言中:

    • 符号(Symbol):表示唯一的、不可变的值,用于保护属性名、实现私有属性或方法等场景。

    Symbol的起源

    在JavaScript诞生之初,对象属性只能使用字符串作为键,这导致了一些问题。例如,当两个不同的对象试图使用相同的字符串作为属性名时,可能会导致属性名冲突。此外,JavaScript中没有一种简单的方法来实现私有属性或方法。

    其实对于Symbol的追溯早在Lisp语言中就有体现:

    (setq x (intern "my-symbol"))

    这里其实就是创建了一个名为my-symbol的符号对象,并将其赋值给变量x

    另外,ES6引入Symbol其实离不开Ruby的身影,在Ruby中,可以使用冒号(:)来创建符号。冒号后面跟着符号的名称,如:

    :my_symbol

    可以看到其实Ruby的语法更加简洁,定义和使用都是用冒号区分:

    person = {  'name' => 'John',  'age' => 30,  :gender => 'Male'}puts person[:gender]  # 输出:'Male'

    所以,在这样的需求背景下,ES6在首批特性中包含了Symbol也不足为奇了。

    Symbol的基本知识

    定义与使用

    JavaScript中,可以使用Symbol()函数来创建一个符号,如下所示:

    const mySymbol = Symbol();

    Symbol函数可以接受一个描述性字符串作为参数,用于标识符号的含义,如下所示:

    const mySymbol = Symbol('my symbol');

    需要注意的是,每个Symbol()函数调用都会返回一个唯一的符号,即使描述性字符串相同,它们也是不同的符号。

    Symbol类型的值可以用作对象的属性名,如下所示:

    const mySymbol = Symbol('my symbol');const myObject = {  [mySymbol]: 'hello'};console.log(myObject[mySymbol]);  // 输出:'hello'

    在上面的代码中,我们使用符号mySymbol作为对象myObject的属性名,并将其值设置为'hello'。使用符号作为属性名的好处是它们不会与其他属性名冲突,并且对外不可见,因此可以用于实现私有属性或方法等场景。

    另外,JavaScript中的Symbol类型有两个特殊的方法Symbol.for()Symbol.keyFor(),用于创建全局符号和获取已经存在的全局符号。

    • Symbol.for(): 用于创建或获取一个全局符号,如果全局符号已经存在,则返回已经存在的符号,否则创建一个新的全局符号。例如:

    const mySymbol = Symbol.for('my symbol');const sameSymbol = Symbol.for('my symbol');console.log(mySymbol === sameSymbol);  // 输出:true

    在上面的代码中,我们使用Symbol.for()方法来创建一个全局符号'my symbol',并将其赋值给mySymbol变量。然后,我们再次使用Symbol.for()方法来获取同一个全局符号,赋值给sameSymbol变量。由于全局符号已经存在,因此sameSymbol变量的值等于mySymbol变量的值,输出true

    Symbol的重要属性

    1. Symbol.iterator: 用于指定对象的默认迭代器,例如:

    const myObject = {  *[Symbol.iterator]() {    yield 1;    yield 2;    yield 3;  }};for (const value of myObject) {  console.log(value);}// 输出:1 2 3

    在上面的代码中,我们为myObject对象设置了Symbol.iterator符号,并指定了一个生成器函数作为迭代器的实现。然后,我们可以使用for...of循环迭代myObject对象,并输出其中的值。

    2. Symbol.hasInstance: 用于定义一个对象是否为某个构造函数的实例。

    Symbol.hasInstance方法接受一个参数,表示要检查的对象。该方法需要返回一个布尔值,表示该对象是否为该构造函数的实例。例如:

    class MyClass {  static [Symbol.hasInstance](obj) {    return obj instanceof Array;  }}console.log([] instanceof MyClass);  // 输出:trueconsole.log({} instanceof MyClass);  // 输出:false

    在上面的代码中,我们定义了一个MyClass类,并使用Symbol.hasInstance方法自定义了instanceof运算符的行为,使其检查对象是否为数组。当检查[]对象时,instanceof运算符返回true,因为[]是Array的实例;当检查{}对象时,instanceof运算符返回false,因为{}不是Array的实例。

    需要注意的是,Symbol.hasInstance方法是一个静态方法,需要定义在构造函数的静态属性中。另外,Symbol.hasInstance方法不能被继承,因此子类需要重新定义该方法。

    3. Symbol.toStringTag: 用于自定义对象的默认字符串描述。

    当调用Object.prototype.toString()方法时,会使用该对象的Symbol.toStringTag属性作为默认的字符串描述,例如:

    class MyObject {  get [Symbol.toStringTag]() {    return 'MyObject';  }}const obj = new MyObject();console.log(Object.prototype.toString.call(obj));  // 输出:'[object MyObject]'

    在上面的代码中,我们定义了一个MyObject类,并使用Symbol.toStringTag属性自定义了该类的默认字符串描述。然后,我们创建了一个obj对象,并使用Object.prototype.toString()方法获取其字符串描述,输出'[object MyObject]'

    需要注意的是,Symbol.toStringTag属性只有在调用Object.prototype.toString()方法时才会生效,对其他方法没有影响。另外,如果没有定义Symbol.toStringTag属性,则默认使用构造函数的名称作为字符串描述。

    4. Symbol.asyncIterator: 用于指定对象的默认异步迭代器。

    当使用for await...of循环迭代一个对象时,会调用该对象的Symbol.asyncIterator方法获取异步迭代器。

    Symbol.asyncIterator方法需要返回一个异步迭代器对象,该对象实现了next()方法,并返回一个Promise对象。当迭代器迭代到结束时,next()方法应该返回一个Promise对象,该Promise对象的value属性为undefineddone属性为true

    例如,下面的代码演示了如何使用Symbol.asyncIterator属性定义一个异步迭代器:

    const myObject = {  async *[Symbol.asyncIterator]() {    yield Promise.resolve(1);    yield Promise.resolve(2);    yield Promise.resolve(3);  }};(async function() {  for await (const value of myObject) {    console.log(value);  }})();// 输出:1 2 3

    在上面的代码中,我们为myObject对象设置了Symbol.asyncIterator符号,并指定了一个异步生成器函数作为异步迭代器的实现。然后,我们使用for await...of循环迭代myObject对象,并输出其中的值。

    需要注意的是,使用Symbol.asyncIterator属性定义的异步迭代器只能使用for await...of循环进行迭代,不能使用普通的for...of循环。此外,Symbol.asyncIterator属性只有在支持异步迭代器的环境中才能使用,例如Node.js的版本必须在10.0.0以上才支持异步迭代器。

    Symbol的实现原理

    symbol作为基本数据类型实现比较简单,在最新的v8代码实现如下:

    Symbol Factory::NewSymbolInternal(AllocationType allocation) {  DCHECK(allocation != AllocationType::kYoung);  // Statically ensure that it is safe to allocate symbols in paged spaces.  STATIC_ASSERT(Symbol::kSize <= kMaxRegularHeapObjectSize);  Symbol symbol = Symbol::cast(AllocateRawWithImmortalMap(      Symbol::kSize, allocation, read_only_roots().symbol_map()));  DisallowGarbageCollection no_gc;  // Generate a random hash value.  int hash = isolate()->GenerateIdentityHash(Name::kHashBitMask);  symbol.set_raw_hash_field(Name::kIsNotIntegerIndexMask |                            (hash << Name::kHashShift));  symbol.set_description(read_only_roots().undefined_value(),                         SKIP_WRITE_BARRIER);  symbol.set_flags(0);  DCHECK(!symbol.is_private());  return symbol;}

    该函数使用AllocateRawWithImmortalMap()方法为新的Symbol对象分配内存,并将其强制转换为Symbol类型。接着,该函数使用DisallowGarbageCollection类禁用垃圾回收器,以确保不会在生成哈希值的过程中触发垃圾回收。接下来,该函数使用GenerateIdentityHash()方法生成一个随机的哈希值,并将其存储在新的Symbol对象中。然后,该函数将Symbol对象的描述设置为undefined,并将其标志设置为0。最后,该函数返回新创建的Symbol对象。

    所以使用hash来唯一标识一个symbol,在v8内部还实现了symbol-table来实现Symbol.for的查找,本质上也是一个哈希表。

    为了简单起见,我们用js来模拟一下Symbol的实现:

    const registry = {};function createSymbol(description) {  const symbol = Object.create(null);  symbol.toString = () => `Symbol(${description || ''})`;  Object.defineProperty(symbol, 'description', {    value: description,    writable: false,    configurable: false,    enumerable: false,  });  return symbol;}function Symbol(description) {  if (typeof description !== 'undefined') {    description = String(description);  }  if (registry[description]) {    return registry[description];  }  const symbol = createSymbol(description);  registry[description] = symbol;  return symbol;}Symbol.for = function (key) {  if (registry[key]) {    return registry[key];  }  const symbol = createSymbol(key);  registry[key] = symbol;  return symbol;};Symbol.keyFor = function (symbol) {  for (const key in registry) {    if (registry.hasOwnProperty(key) && registry[key] === symbol) {      return key;    }  }};export default Symbol;

    我们使用一个全局对象registry来存储Symbol对象及其描述符信息。createSymbol()函数用于创建新的Symbol对象,其中使用了Object.create()方法来创建一个没有原型的对象,并通过定义toString()description属性来实现Symbol对象的基本功能。Symbol()函数用于创建新的Symbol对象,它根据传入的描述符信息从registry中查找Symbol对象,如果找到了则返回已有的Symbol对象,否则创建新的Symbol对象并添加到registry中。

    Symbol的使用场景

    SymbolVSCode的应用其实不多,最新的代码只有:

    export const MicrotaskDelay = Symbol('MicrotaskDelay');

    在实际中,Symbol经常被用于:

    1. 唯一属性键:Symbol可以作为对象属性的键,避免属性名冲突。

    这在创建第三方库或插件时非常有用,因为可以确保库或插件的属性不会与其他代码意外冲突。

    const uniqueKey = Symbol('uniqueKey');const obj = {  [uniqueKey]: 'This value is uniquely keyed'};

    2. 定义私有属性(当然这一点现在ES规范已经有更好的方式了)

    使用Symbol可以在对象上创建"私有"属性,它们不会被常规的属性枚举(如for...inObject.keys()JSON.stringify())包含在内。这有助于保护对象内部实现细节。

    3. 内置Symbol

    JavaScript内置了一些具有特定功能的Symbol。例如,Symbol.iterator可以定义对象的迭代行为,Symbol.toStringTag可以自定义Object.prototype.toString.call()方法的输出。

    4. 注册全局Symbol

    Symbol.for()方法允许在全局Symbol注册表中创建或获取Symbol。这对于跨多个地方或模块使用相同的Symbol时非常有用。

    const globalSymbol = Symbol.for('globalSymbol');const sameGlobalSymbol = Symbol.for('globalSymbol');console.log(globalSymbol === sameGlobalSymbol); // true

    Symbol的发展

    tc39上已经有两个关于Symbol的提案:

    Symbols as WeakMap keys(Stage3)

    Symbol作为一种新的数据类型,其功能和用途都比较有限,因此tc39Symbol的基础上提出了一些新的提案,以扩展其功能和用途。其中一个比较重要的提案是Symbols as WeakMap keys,该提案已经进入到Stage3阶段。

    WeakMap是一种新的集合类型,可以用于存储对象和关联的元数据。WeakMap的特点是键必须是对象,值可以是任意类型。WeakMap的另一个特点是,当键对象不再被引用时,WeakMap会自动删除该键值对,以避免内存泄漏。

    Symbols as WeakMap keys提案的目的是将Symbol作为WeakMap的键。这样,就可以在不影响WeakMap的自动垃圾回收机制的情况下,将Symbol作为对象的元数据来使用。

    const weak = new WeakMap();// Pun not intended: being a symbol makes it become a more symbolic keyconst key = Symbol('my ref');const someObject = {  };weak.set(key, someObject);

    Symbol Predicates Proposal(Stage2)

    这是另一个关于Symbol的提案,添加了以下判断方法:Symbol.isRegistered(symbol)Symbol.isWellKnown(symbol)

    其实对于库作者而言,了解更多关于Symbol的信息是很重要的。根据使用情况,了解一个Symbol是否真正唯一、可伪造(已注册)或跨域共享(众所周知)可能非常关键。例如,将Symbol用作WeakMap键需要确保Symbol未被注册。该提案处于第二阶段,正在受到JavaScript社区的广泛关注。如果被采纳,它将为Symbol的应用带来更多的灵活性。

    function isWeakMapKey(key) {  switch (typeof key) {    case "object":      return key !== null;    case "function":      return true;    case "symbol":      return !Symbol.isRegistered(sym);  }  return false;}isWeakMapKey({}); // trueisWeakMapKey(Symbol()); // trueisWeakMapKey("foo"); // falseisWeakMapKey(Symbol.for("foo")); // falseisWeakMapKey(Symbol.asyncIterator); // true

    您还可以检查是否获得了真正唯一的Symbol

    const isUniqueSymbol = sym => typeof sym === "symbol" && !(Symbol.isRegistered(sym) || Symbol.isWellKnown(sym));isUniqueSymbol(Symbol()); // trueisUniqueSymbol(Symbol.for("foo")); // falseisUniqueSymbol(Symbol.asyncIterator); // falseisUniqueSymbol({}); // false

    关于“vscode工具函数Symbol如何使用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网行业资讯频道,小编每天都会为大家更新不同的知识点。

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    vscode工具函数Symbol如何使用

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    vscode工具函数Symbol如何使用

    这篇文章主要介绍“vscode工具函数Symbol如何使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“vscode工具函数Symbol如何使用”文章能帮助大家解决问题。什么是Symbol?符号(S
    2023-07-05

    vscode工具函数once如何使用

    这篇文章主要介绍“vscode工具函数once如何使用”,在日常操作中,相信很多人在vscode工具函数once如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”vscode工具函数once如何使用”的疑
    2023-07-05

    vscode工具函数idGenerator怎么使用

    这篇文章主要介绍“vscode工具函数idGenerator怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“vscode工具函数idGenerator怎么使用”文章能帮助大家解决问题。vsco
    2023-07-05

    vscode如何使用nuget包管理工具

    这篇文章主要讲解了“vscode如何使用nuget包管理工具”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vscode如何使用nuget包管理工具”吧!一、使用dotnet add pack
    2023-07-01

    如何使用工具分析 golang 函数

    回答:分析 go 函数需要使用 pprof 和 flamegraph 两个工具。步骤:使用 pprof 生成性能配置文件。可视化配置文件并识别热点函数。使用 flamegraph 生成火焰图。通过火焰图分析函数调用关系。使用 pprof 和
    如何使用工具分析 golang 函数
    2024-05-07

    如何使用工具生成 Golang 函数文档?

    命令 godoc -markdown=index.md 可生成 go 函数文档,通过打开生成的文件 index.md 查看文档。具体步骤为:1. 保存 go 文件;2. 运行命令 godoc -markdown=index.md。如何使用工
    如何使用工具生成 Golang 函数文档?
    2024-05-06

    如何使用 GoDoc 工具生成 Golang 函数文档?

    godoc 工具可以通过以下步骤生成 golang 函数文档:为函数编写包含函数签名和描述的注释。运行 godoc 命令(godoc -http=:6060)生成文档。在浏览器中访问生成的文档(http://localhost:6060/p
    如何使用 GoDoc 工具生成 Golang 函数文档?
    2024-04-18

    如何使用 PHP 内置的函数调试工具?

    php 内置调试工具包括 print_r()、var_dump() 和 debug_backtrace() 等,它们分别以人可读方式打印变量值、提供更详细的变量信息,以及创建包含调用堆栈信息的数组。实战案例中,你可以使用 var_dump(
    如何使用 PHP 内置的函数调试工具?
    2024-04-18

    Linux exit函数如何配合调试工具使用

    在 Linux 系统中,exit() 函数是一个标准库函数,用于正常终止程序gdb:GNU 调试器(gdb)是一个功能强大的源代码级调试工具。要使用 gdb 调试一个程序并设置断点,请按照以下步骤操作:a. 首先,确保你的程序已经使用 -
    Linux exit函数如何配合调试工具使用
    2024-09-09

    如何使用工具分析 PHP 函数性能瓶颈?

    php 函数性能分析工具:安装 xdebug,分析函数执行时间和内存使用情况。使用 blackfire 分析函数性能,生成交互式图表和详细报告。如何使用工具分析 PHP 函数性能瓶颈在进行 PHP 开发时,优化函数性能至关重要。借助各种工
    如何使用工具分析 PHP 函数性能瓶颈?
    2024-04-25

    如何用工具优化 golang 函数性能

    golang 函数性能优化工具有:pprof:分析程序性能和内存使用情况,识别耗时的代码段。benchstat:比较不同函数或算法的性能,提供详细统计信息。go test -bench:内置基准测试功能,评估函数性能并查看基准测试报告。优化
    如何用工具优化 golang 函数性能
    2024-05-06

    Golang函数如何用于命令行工具?

    go 函数可将命令行工具的复杂功能分解为可管理的模块,从而提高代码的可维护性和可读性。以下步骤说明了 go 函数在命令行工具中的作用:定义函数来执行特定任务。在主函数中调用函数,传入适当的参数。函数执行任务并返回结果。主函数处理结果并执行后
    Golang函数如何用于命令行工具?
    2024-04-12

    如何使用工具来提高 Golang 函数调试效率?

    使用工具可提升 go 函数调试效率:delve 是一款强大的 ui 调试器,可实时检查数据和执行流。gdb 则是一款命令行调试器,支持高级功能,如反汇编和内存检查。这些工具通过设置断点、逐行执行代码和查看变量值,简化了复杂函数的调试过程,提
    如何使用工具来提高 Golang 函数调试效率?
    2024-04-17

    JavaScript数组常用工具函数怎么使用

    这篇文章主要讲解了“JavaScript数组常用工具函数怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript数组常用工具函数怎么使用”吧!一. 实现Array.isAr
    2023-07-02

    git工具如何使用

    git工具是一个非常常用的版本控制系统,它可以帮助程序员管理代码,协作开发,以及版本控制,而且非常易于使用。本文将会详细讲解如何使用git工具。一、Git的安装与配置首先,我们要安装Git工具。去官方网站下载对应操作系统的安装包,然后进行安
    2023-10-22

    使用工具深入了解 golang 函数

    通过 go tool objdump 命令可深入了解 go 函数的汇编代码,从而洞察其内部工作原理。例如,查看 strconv.parseint 源代码,了解其如何将字符串转换为 int64,包含以下步骤:1. 查找非空格字符起始位置。2.
    使用工具深入了解 golang 函数
    2024-05-06

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录