记录-Symbol学习笔记

news2024/11/24 11:54:35

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

Symbol是JavaScript中的原始数据类型之一,它表示一个唯一的、不可变的值,通常用作对象属性的键值。由于Symbol值是唯一的,因此可以防止对象属性被意外地覆盖或修改。以下是Symbol的方法和属性整理:

属性

Symbol.length

Symbol构造函数的length属性值为0。

示例代码:

console.log(Symbol.length); // 0

方法

Symbol.for()

Symbol.for()方法会根据给定的字符串key,返回一个已经存在的symbol值。如果不存在,则会创建一个新的Symbol值并将其注册到全局Symbol注册表中。

示例代码:

const symbol1 = Symbol.for('foo');
const symbol2 = Symbol.for('foo');

console.log(symbol1 === symbol2); // true

使用场景: 当我们需要使用一个全局唯一的Symbol值时,可以使用Symbol.for()方法来获取或创建该值。例如,在多个模块之间共享某个Symbol值时,我们可以使用Symbol.for()来确保获取到的Symbol值是唯一的。

Symbol.keyFor()

Symbol.keyFor()方法会返回一个已经存在的Symbol值的key。如果给定的Symbol值不存在于全局Symbol注册表中,则返回undefined。

示例代码:

const symbol1 = Symbol.for('foo');
const key1 = Symbol.keyFor(symbol1);

const symbol2 = Symbol('bar');
const key2 = Symbol.keyFor(symbol2);

console.log(key1); // 'foo'
console.log(key2); // undefined

使用场景: 当我们需要获取一个全局唯一的Symbol值的key时,可以使用Symbol.keyFor()方法。但需要注意的是,只有在该Symbol值被注册到全局Symbol注册表中时,才能使用Symbol.keyFor()方法获取到其key。

Symbol()

Symbol()函数会返回一个新的、唯一的Symbol值。可以使用可选参数description来为Symbol值添加一个描述信息。

示例代码:

const symbol1 = Symbol('foo');
const symbol2 = Symbol('foo');

console.log(symbol1 === symbol2); // false

使用场景: 当我们需要使用一个唯一的Symbol值时,可以使用Symbol()函数来创建该值。通常情况下,我们会将Symbol值用作对象属性的键值,以确保该属性不会被意外地覆盖或修改。

Symbol.prototype.toString()

Symbol.prototype.toString()方法会返回Symbol值的字符串表示形式,该表示形式包含Symbol()函数创建时指定的描述信息。

示例代码:

const symbol = Symbol('foo');

console.log(symbol.toString()); // 'Symbol(foo)'

使用场景: 当我们需要将一个Symbol值转换成字符串时,可以使用Symbol.prototype.toString()方法。

Symbol.prototype.valueOf()

Symbol.prototype.valueOf()方法会返回Symbol值本身。

示例代码:

const symbol = Symbol('foo');

console.log(symbol.valueOf()); // Symbol(foo)

使用场景: 当我们需要获取一个Symbol值本身时,可以使用Symbol.prototype.valueOf()方法。

Symbol.iterator

Symbol.iterator是一个预定义好的Symbol值,表示对象的默认迭代器方法。该方法返回一个迭代器对象,可以用于遍历该对象的所有可遍历属性。

示例代码:

const obj = { a: 1, b: 2 };

for (const key of Object.keys(obj)) {
  console.log(key);
}
// Output:
// 'a'
// 'b'

for (const key of Object.getOwnPropertyNames(obj)) {
  console.log(key);
}
// Output:
// 'a'
// 'b'

for (const key of Object.getOwnPropertySymbols(obj)) {
  console.log(key);
}
// Output: 
// No output

obj[Symbol.iterator] = function* () {
  for (const key of Object.keys(this)) {
    yield key;
  }
}

for (const key of obj) {
  console.log(key);
}
// Output:
// 'a'
// 'b'

使用场景: 当我们需要自定义一个对象的迭代行为时,可以通过定义Symbol.iterator属性来实现。例如,对于自定义的数据结构,我们可以定义它的Symbol.iterator方法以便能够使用for...of语句进行遍历。

Symbol.hasInstance

Symbol.hasInstance是一个预定义好的Symbol值,用于定义对象的 instanceof 操作符行为。当一个对象的原型链中存在Symbol.hasInstance方法时,该对象可以被instanceof运算符使用。

示例代码:

class Foo {
  static [Symbol.hasInstance](obj) {
    return obj instanceof Array;
  }
}

console.log([] instanceof Foo); // true
console.log({} instanceof Foo); // false

使用场景: 当我们需要自定义一个对象的 instanceof 行为时,可以通过定义Symbol.hasInstance方法来实现。

Symbol.isConcatSpreadable

Symbol.isConcatSpreadable是一个预定义好的Symbol值,用于定义对象在使用concat()方法时的展开行为。如果一个对象的Symbol.isConcatSpreadable属性为false,则在调用concat()方法时,该对象不会被展开。

示例代码:

const arr1 = [1, 2];
const arr2 = [3, 4];
const obj = { length: 2, 0: 5, 1: 6, [Symbol.isConcatSpreadable]: false };

console.log(arr1.concat(arr2)); // [1, 2, 3, 4]
console.log(arr1.concat(obj)); // [1, 2, { length: 2, 0: 5, 1: 6, [Symbol(Symbol.isConcatSpreadable)]: false }]

使用场景: 当我们需要自定义一个对象在使用concat()方法时的展开行为时,可以通过定义Symbol.isConcatSpreadable属性来实现。

Symbol.toPrimitive

Symbol.toPrimitive是一个预定义好的Symbol值,用于定义对象在被强制类型转换时的行为。如果一个对象定义了Symbol.toPrimitive方法,则在将该对象转换为原始值时,会调用该方法。

示例代码:

const obj = {
  valueOf() {
    return 1;
  },
  [Symbol.toPrimitive](hint) {
    if (hint === 'number') {
      return 2;
    } else if (hint === 'string') {
      return 'foo';
    } else {
      return 'default';
    }
  }
};

console.log(+obj); // 2
console.log(`${obj}`); // 'foo'
console.log(obj + ''); // 'default'

使用场景: 当我们需要自定义一个对象在被强制类型转换时的行为时,可以通过定义Symbol.toPrimitive方法来实现。

Symbol.toStringTag

Symbol.toStringTag是一个预定义好的Symbol值,用于定义对象在调用Object.prototype.toString()方法时返回的字符串。如果一个对象定义了Symbol.toStringTag属性,则在调用该对象的toString()方法时,会返回该属性对应的字符串。

示例代码:

class Foo {
  get [Symbol.toStringTag]() {
    return 'Bar';
  }
}

console.log(Object.prototype.toString.call(new Foo())); // '[object Bar]'

使用场景: 当我们需要自定义一个对象在调用Object.prototype.toString()方法时返回的字符串时,可以通过定义Symbol.toStringTag属性来实现。

Symbol.species

Symbol.species是一个预定义好的Symbol值,用于定义派生对象的构造函数。如果一个对象定义了Symbol.species属性,则在调用该对象的派生方法(如Array.prototype.map())时,返回的新对象会使用该属性指定的构造函数。

示例代码:

class MyArray extends Array {
  static get [Symbol.species]() {
    return Array;
  }
}

const myArr = new MyArray(1, 2, 3);
const arr = myArr.map(x => x * 2);

console.log(arr instanceof MyArray); // false
console.log(arr instanceof Array); // true

使用场景: 当我们需要自定义一个派生对象的构造函数时,可以通过定义Symbol.species属性来实现。

Symbol.match

Symbol.match是一个预定义好的Symbol值,用于定义对象在调用String.prototype.match()方法时的行为。如果一个对象定义了Symbol.match方法,则在调用该对象的match()方法时,会调用该方法进行匹配。

示例代码:

class Foo {
  [Symbol.match](str) {
    return str.indexOf('foo') !== -1;
  }
}

console.log('foobar'.match(new Foo())); // true
console.log('barbaz'.match(new Foo())); // false

使用场景: 当我们需要自定义一个对象在调用String.prototype.match()方法时的行为时,可以通过定义Symbol.match方法来实现。

Symbol.replace

Symbol.replace是一个预定义好的Symbol值,用于定义对象在调用String.prototype.replace()方法时的行为。如果一个对象定义了Symbol.replace方法,则在调用该对象的replace()方法时,会调用该方法进行替换。

示例代码:

class Foo {
  [Symbol.replace](str, replacement) {
    return str.replace('foo', replacement);
  }
}

console.log('foobar'.replace(new Foo(), 'baz')); // 'bazbar'
console.log('barbaz'.replace(new Foo(), 'baz')); // 'barbaz'

使用场景: 当我们需要自定义一个对象在调用String.prototype.replace()方法时的行为时,可以通过定义Symbol.replace方法来实现。

Symbol.search

Symbol.search是一个预定义好的Symbol值,用于定义对象在调用String.prototype.search()方法时的行为。如果一个对象定义了Symbol.search

class Foo {
  [Symbol.search](str) {
    return str.indexOf('foo');
  }
}

console.log('foobar'.search(new Foo())); // 0
console.log('barbaz'.search(new Foo())); // -1

使用场景: 当我们需要自定义一个对象在调用String.prototype.search()方法时的行为时,可以通过定义Symbol.search方法来实现。

Symbol.split

Symbol.split是一个预定义好的Symbol值,用于定义对象在调用String.prototype.split()方法时的行为。如果一个对象定义了Symbol.split方法,则在调用该对象的split()方法时,会调用该方法进行分割。

示例代码:

class Foo {
  [Symbol.split](str) {
    return str.split(' ');
  }
}

console.log('foo bar baz'.split(new Foo())); // ['foo', 'bar', 'baz']
console.log('foobarbaz'.split(new Foo())); // ['foobarbaz']

使用场景: 当我们需要自定义一个对象在调用String.prototype.split()方法时的行为时,可以通过定义Symbol.split方法来实现。

Symbol.iterator

Symbol.iterator是一个预定义好的Symbol值,用于定义对象在被遍历时的行为。如果一个对象定义了Symbol.iterator方法,则可以使用for...of循环、扩展运算符等方式来遍历该对象。

示例代码:

class Foo {
  constructor() {
    this.items = ['foo', 'bar', 'baz'];
  }

  *[Symbol.iterator]() {
    for (const item of this.items) {
      yield item;
    }
  }
}

const foo = new Foo();

for (const item of foo) {
  console.log(item);
}

// 'foo'
// 'bar'
// 'baz'

使用场景: 当我们需要自定义一个对象在被遍历时的行为时,可以通过定义Symbol.iterator方法来实现。比如,我们可以通过实现Symbol.iterator方法来支持自定义数据结构的遍历。

Symbol.toPrimitive

Symbol.toPrimitive是一个预定义好的Symbol值,用于定义对象在被强制类型转换时的行为。如果一个对象定义了Symbol.toPrimitive方法,则可以通过调用该方法来进行强制类型转换。

示例代码:

const obj = {
  valueOf() {
    return 1;
  },
  [Symbol.toPrimitive](hint) {
    if (hint === 'default') {
      return 'default';
    } else if (hint === 'number') {
      return 2;
    } else {
      return 'foo';
    }
  }
};

console.log(+obj); // 2
console.log(`${obj}`); // 'foo'
console.log(obj + ''); // 'default'

使用场景: 当我们需要自定义一个对象在被强制类型转换时的行为时,可以通过定义Symbol.toPrimitive方法来实现。

Symbol.toStringTag

Symbol.toStringTag是一个预定义好的Symbol值,用于定义对象在调用Object.prototype.toString()方法时返回的字符串。如果一个对象定义了Symbol.toStringTag属性,则在调用该对象的toString()方法时,会返回该属性对应的字符串。

示例代码:

class Foo {
  get [Symbol.toStringTag]() {
    return 'Bar';
  }
}

console.log(Object.prototype.toString.call(new Foo())); // '[object Bar]'

使用场景: 当我们需要自定义一个对象在调用Object.prototype.toString()方法时返回的字符串时,可以通过定义Symbol.toStringTag属性来实现。这样做有助于我们更清晰地表示对象的类型。

Symbol.unscopables

Symbol.unscopables是一个预定义好的Symbol值,用于定义对象在使用with语句时的行为。如果一个对象定义了Symbol.unscopables属性,则在使用with语句时,该对象的指定属性将不会被绑定到with语句的环境中。

示例代码:

const obj = {
  a: 1,
  b: 2,
  c: 3,
  [Symbol.unscopables]: {
    c: true
  }
};

with (obj) {
  console.log(a); // 1
  console.log(b); // 2
  console.log(c); // ReferenceError: c is not defined
}

使用场景: 由于with语句会带来一些安全性问题和性能问题,因此在实际开发中不建议使用。但是,如果确实需要使用with语句,可以通过定义Symbol.unscopables属性来避免某些属性被误绑定到with语句的环境中。

Symbol.hasInstance

Symbol.hasInstance是一个预定义好的Symbol值,用于定义对象在调用instanceof运算符时的行为。如果一个对象定义了Symbol.hasInstance方法,则在调用该对象的instanceof运算符时,会调用该方法来判断目标对象是否为该对象的实例。

示例代码:

class Foo {
  static [Symbol.hasInstance](obj) {
    return Array.isArray(obj);
  }
}

console.log([] instanceof Foo); // true
console.log({} instanceof Foo); // false

使用场景: 当我们需要自定义一个对象在调用instanceof运算符时的行为时,可以通过定义Symbol.hasInstance方法来实现。比如,我们可以通过实现Symbol.hasInstance方法来支持自定义数据类型的判断。

总结

Symbol是ES6中新增的一种基本数据类型,用于表示独一无二的值。Symbol值在语言层面上解决了属性名冲突的问题,可以作为对象的属性名使用,并且不会被意外覆盖。除此之外,Symbol还具有以下特点:

  • Symbol值是唯一的,每个Symbol值都是独一无二的,即使是通过相同的描述字符串创建的Symbol值,也不会相等;
  • Symbol值可以作为对象的属性名使用,并且不会被意外覆盖;
  • Symbol值可以作为私有属性来使用,因为无法通过对象外部访问对象中的Symbol属性;
  • Symbol值可以被用作常量,因为它们是唯一的;
  • Symbol值可以用于定义迭代器、类型转换规则、私有属性、元编程等高级功能。

在使用Symbol时需要注意以下几点:

  • Symbol值不能使用new运算符创建;
  • Symbol值可以通过描述字符串来创建,但是描述字符串并不是Symbol值的唯一标识符;
  • Symbol属性在使用时需要用[]来访问,不能使用.运算符;
  • 同一对象中的多个Symbol属性是独立的,它们之间不会互相影响。

总之,Symbol是一个非常有用的数据类型,在JavaScript中具有非常广泛的应用。使用Symbol可以有效地避免属性名冲突问题,并且可以为对象提供一些高级功能。熟练掌握Symbol,有助于我们写出更加健壮、高效和可维护的JavaScript代码。

本文转载于:

https://juejin.cn/post/7226193000496463928

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/494544.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Word下划线怎么打?速速get这5个实用方法!

案例:Word下划线怎么打? 【朋友们,最近在写毕业论文,封面文字的下划线打了好久都打不出来,请问大家Word下划线是怎么打的呀?】 在Microsoft Word中,打下划线是一种常见的操作,它可…

Python小姿势 - ## Python与数据库

Python与数据库 简介 当今,数据库是计算机应用中最重要的部分。几乎所有的大型应用都要用到数据库,比如银行、电商、航空、政府、医疗、教育、科研等。数据库的目的是存储数据,并且能够根据用户的需求提供数据。 数据库管理系统(D…

QQ音乐银河音效技术实践——音乐重放效果的补偿与修饰

音效渲染是音频或音乐播放器最为重要的后处理模块之一。LiveVideoStackCon 2022 北京站邀请到腾讯音乐银河音效开发负责人——闫震海,为大家介绍银河音效在QQ音乐播放器中的创新应用,包括空间环绕效果和音效制作工具等内容。 文/闫震海 编辑/LiveVideoSt…

取代你的可能不是AI,而是比你更会使用AI的人

1、背景 从开始了解AI到现在已经1个月了,最明显的就是,产品层出不穷,以前只有技术人员才关系AI,现在各行各业都在关系AI,都希望通过它提高生产力和创造力; 在当今大数据和人工智能时代,职场和企…

MySQL基础(一)数据库概述

1. 为什么要使用数据库 持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用。大多数情况下,特别是企业级应用,数据持久化意味着将内存中的数据保存到硬盘上加以”固化”,而持久化的实现过程大多通过各种关系数据库…

Linux网络基础-2

在之前的网络基础博客中,我们对网络的基本概念进行了一个简单的介绍,那么接下来的网络内容中,我们将对网络通信中的典型协议进行详细解释。 我们根据网络协议中的分层来对典型协议进行注意介绍,不过对于物理层的传输我们不做考究…

docker安装mongodb出现bash: mongo: command not found

安装MongoDB容器 -e MONGO_INITDB_ROOT_USERNAME创建管理员账号 -e MONGO_INITDB_ROOT_PASSWORD123456创建密码 映射容器服务的 27017 端口到宿主机的 27017 端口 docker run -d -p 27017:27017 --name mongodb -e MONGO_INITDB_ROOT_USERNAMEadmin -e MONGO_INITDB_ROOT_PAS…

简单分享微信里怎么添加投票活动

今天小编要分享是投票活动,怎么做投票活动,首先要做投票活动是需要用到第三方平台,这样我们才可以快速的制作出投票活动链接,其次我们是在微信小程序上添加投票活动的话,我们需要有微信小程序平台,然后把二…

数字信号处理2:频率

频率这个东西,说实话,我记得好像是初中还是小学的时候,刚接触三角函数的时候老师就已经开始给我们教频率了,但是,因为一直没有碰过信号,所以对频率也就没怎么关注过。 频率就是周期的倒数,这是…

Centos7 DolphinScheduler集群部署

DolphinScheduler集群部署 1 DolphinScheduler集群部署1.1 DolphinScheduler简介1.2 集群规划1.3 前置准备工作1.4 DolphinScheduler集群部署1.4.1 解压DolphinScheduler安装包1.4.2 创建元数据库及用户1.4.3 配置一键部署脚本1.4.4 初始化数据库1.4.5 配置部署用户免密及权限1…

中国网络安全人才需求

如果你是一个想要入门网络安全行业的小白、如果你是网络安全专业在读的大学生、如果你是正在找工作的新手,那么这篇文章你一定要仔细看。毕竟知己知彼百战百胜,知道行业的人才需求才能更好得发挥自己的优势。 当你打开BOSS直聘、拉钩等招聘网站&#xf…

打动人心的故事 | 如何利用文案在Facebook上塑造品牌形象

在当今的数字营销时代,文案已经成为各大平台上不可或缺的元素之一。在Facebook上,一个好的文案能够为品牌带来巨大的曝光率和用户黏性,甚至可以改变用户对品牌的看法。那么,如何利用文案在Facebook上打动人心,塑造品牌…

Office Tool Plus的使用

是否为安装,卸载,激活Office而烦恼? 下载 地址:Office Tool Plus 官方网站 - 一键部署 Office 安装office 先安装Office,Office_Pro_Plus_2021_LTSCProjectVisio_x64_zh_CN_VL_2022-02 注意,要安装批量…

亚马逊云科技能为“医疗和生命科学”做些什么?

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 4月27日,亚马逊云科技医疗与生命科学行业峰会在上海盛大召开,会议汇聚了业界专家和思想领袖,共同探讨行业数字化转型和创新之道。 “医疗及生命科学”是人类社会永恒的命题,科…

爱创科技参加基于GS1标准的医药全球追溯体系建设研讨会

2023 年 4 月 26 日,由中国化学制药工业协会、中国物品编码中心、北京药盾公益基金会联合主办的以“携手迎接药品全球化挑战——基于GS1标准的医药全球追溯体系建设”为主题的研讨会在上海成功举办,爱创科技作为支持单位参加了本次会议,爱创科…

JQuery实现自定义滚动条

在页面中虽然可以通过CSS修改滚动条的样式,但是部分属性是无法自己修改和设置的,而且不同浏览器存在兼容问题,因此通过JS来实现滚动条在自定义滚动条的环境下也是有必要的。 接下来,我们来实现上图两种情况下滚动条的实现。 一、页面搭建 1.…

深浅拷贝以及解决浅拷贝(以string浅拷贝为例)

一、什么是浅拷贝 在类和对象的时候,其中编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定义类型是调用其拷贝构造函数完成拷贝的。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅…

第三十五章 Unity人形动画(下)

本章内容主要就是动画数据的独立文件使用方式。有了独立的动画文件,我们就可以将其应用到其他模型上面了。最简单的方式就是,我们可以给其他模型编辑动画控制器的时候,使用这些动画文件。Unity则给我们提供了更加高级的共享方式,就…

【iOS KVO(下) KVO的内部结构和源码】

前言 学习KVO的过程,我分为了KVO的实现过程分析和内部结构的学习,学习了实现过程,接下来看KVO是通过何种内部结构实现如此通知📢和监听。 1 KVO的存储结构 KVO的实现过程离不开合理的存储结构,用到了如下几个类 GS…

Linux + 香橙派 + V4L2 + http 实现远程监控摄像头在网页端显示

项目场景: 项目需求,需要做一个基于边缘端的人脸识别远程监控摄像头并在网页前端展示 ,这里采用国产香橙派作为边缘计算终端,安装ubuntu系统,系统中采用v4l2接口对摄像头进行获取,当客户端通过网页进行请求…