JS【详解】Symbol (含Symbol 作为属性名,静态方法for 和 keyFor,11 个内置的 Symbol 值)

ES6 语法,表示唯一且不可变的值,常用作属性键值或者唯一标识符。

let a = Symbol()
let a = Symbol('atomic symbol')

console.log(Symbol() === Symbol()) // false
console.log(Symbol('atom') === Symbol('atom')) // false

Symbol 作为属性名

let key = Symbol();
let obj = {
  [key]: "朝阳",
};
  • Symbol 类型值作为属性名,这个属性不会被for…in遍历到,也不会被Object.keys()Object.getOwnPropertyNames()JSON.stringify()获取到;

  • 可以使用Object.getOwnPropertySymbols方法获取对象的所有symbol类型的属性名;

    const name1 = Symbol("name");
    const obj = {
      [name1]: "toimc",
      age: 18
    };
    const SymbolPropNames = Object.getOwnPropertySymbols(obj);
    console.log(SymbolPropNames);
    // [ Symbol(name) ]
    
  • 可以用 ES6 新提供的 Reflect 对象的静态方法Reflect.ownKeys,它可以返回所有类型的属性名:

    console.log(Reflect.ownKeys(obj)); //  ["age", Symbol(name)] 
    

静态方法for 和 keyFor

使用 Symbol.for方法传入字符串,会先检查有没有使用该字符串调用 Symbol.for 方法创建的 symbol 值,如果有,返回该值,如果没有,则使用该字符串新创建一个

const s1 = Symbol("toimc");
const s2 = Symbol("toimc");
const s3 = Symbol.for("toimc");
const s4 = Symbol.for("toimc");

console.log(s3 === s4) // true
console.log(s1 === s3) // false

Symbol.keyFor 方法传入一个 symbol 值,返回该值在全局注册的键名:

const sym = Symbol.for("toimc");
console.log(Symbol.keyFor(sym)); // 'toimc'

内置的 Symbol 值

ES6 提供了 11 个内置的 Symbol 值:

Symbol.hasInstance

当其他对象使用 instanceof 判断是否为这个对象的实例时,会调用你定义的这个方法

const obj = {
  [Symbol.hasInstance](otherObj) {
    console.log(otherObj);
  }
};
console.log({ a: "a" } instanceof obj); // false

Symbol.isConcatSpreadable

当一个数组的 Symbol.isConcatSpreadable 设为 true 时,这个数组在数组的 concat 方法中不会被扁平化。

let arr = [1, 2];
console.log([].concat(arr, [3, 4])); // 打印结果为[1, 2, 3, 4],length为4
let arr1 = ["a", "b"];
console.log(arr1[Symbol.isConcatSpreadable]); // undefined
arr1[Symbol.isConcatSpreadable] = false;
console.log(arr1[Symbol.isConcatSpreadable]); // false
console.log([].concat(arr1, [3, 4])); // [ ["a", "b", Symbol(Symbol.isConcatSpreadable): false], 3, 4 ]

Symbol.species

class C extends Array {
  getName() {
    return "toimc";
  }
}
const c = new C(1, 2, 3);
const a = c.map(item => item + 1);
console.log(a); // [2, 3, 4]
console.log(a instanceof C); // true
console.log(a instanceof Array); // true
console.log(a.getName()); // "toimc"

这个例子中,a 是由 c 通过 map 方法衍生出来的,我们也看到了,a 既是 C 的实例,也是 Array 的实例。但是如果我们想只让衍生的数组是 Array 的实例,就需要用 Symbol.species,我们来看下怎么使用:

class C extends Array {
  // 关键代码:
  static get [Symbol.species]() {
    return Array;
  }
  getName() {
    return "toimc";
  }
}
const c = new C(1, 2, 3);
const a = c.map(item => item + 1);
console.log(a); // [2, 3, 4]
// 这里是false
console.log(a instanceof C); // false
console.log(a instanceof Array); // true
console.log(a.getName()); // error a.getName is not a function

就是给类 C 定义一个静态 get 存取器方法,方法名为 Symbol.species,然后在这个方法中返回要构造衍生数组的构造函数。所以最后我们看到,a instanceof C为 false,也就是 a 不再是 C 的实例,也无法调用继承自 C 的方法。

Symbol.match

当在字符串 str 上调用 match 方法时,会调用这个方法

let obj = {
  [Symbol.match](string) {
    return string.length;
  }
};
console.log("abcde".match(obj)); // 5

Symbol.replace

当在字符串 str 上调用 replace 方法时,会调用这个方法,同上

Symbol.search

当在字符串 str 上调用 search方法时,会调用这个方法,同上

Symbol.split

当在字符串 str 上调用 split 方法时,会调用这个方法,同上

Symbol.iterator

数组的 Symbol.iterator 属性指向该数组的默认遍历器方法:

const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();
console.log(iterator);
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

Symbol.toPrimitive

对象的这个属性指向一个方法,当这个对象被转为原始类型值时会调用这个方法。

这个方法有一个参数,即是这个对象被转为的类型,我们来看下:

let obj = {
  [Symbol.toPrimitive](type) {
    console.log(type);
  }
};
// const b = obj++ // number
const a = `abc${obj}`; // string

Symbol.toStringTag

Symbol.toStringTag 和 Symbol.toPrimitive 相似,对象的这个属性的值可以是一个字符串,也可以是一个存取器 get 方法,当在对象上调用 toString 方法时调用这个方法,返回值将作为"[object xxx]"中 xxx 这个值:

let obj = {
  [Symbol.toStringTag]: "toimc"
};
obj.toString(); // "[object toimc]"
let obj2 = {
  get [Symbol.toStringTag]() {
    return "yoyo";
  }
};
obj2.toString(); // "[object yoyo]"

Symbol.unscopables

这个值和 with 命令有关,但在TS严格模式中,无法使用with。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

适合任何行业在线DIY预约报名小程序源码系统 带完整的安装代码包以及搭建教程

系统概述 在当今数字化时代,便捷高效的预约报名系统成为了许多行业的迫切需求。“适合任何行业在线 DIY 预约报名小程序源码系统”便是一款为满足这一需求而设计开发的创新解决方案。 这款源码系统是基于先进的技术架构,旨在为各类企业和组织提供一个强…

Avalonia 常用控件三 Window窗体相关二

1、效果演示 2、在Views中创建WindowDemo.axaml如下图 WindowDemo.axaml代码如下 <Window xmlns"https://github.com/avaloniaui"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schemas.microsoft.com/expression/blend/…

Python读写文本、图片、xml

Python操作文本、图片、xml 1.Python读写文本1.1文本读取1.2文本写入 2.Python读取、显示图片3.Python读写Xml &#xff08;1&#xff09;Python读写文本 &#xff08;2&#xff09;Python读取、显示图片 &#xff08;3&#xff09;Python读写Xml 1.Python读写文本 新建hellow…

mybatis延迟加载

mybatis延迟加载 1、延迟加载概述 应用场景 ​ 如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求&#xff0c;当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。 延迟加载的好处 ​ 先从单表查询、需要时再从关联表去关联查…

el-input-number 点击加减只能加一次

el-input-number 点击加减只能加一次 <el-input-number v-model"editForm.quantity" placeholder"请输入下单数量(店均)" change"quantityChangeFn"></el-input-number>需要在方法里面加 this.$forceUpdate() quantityChangeFn(val…

web学习笔记(六十九)vue2

目录 1. vue2创建脚手架项目 2.vue2如何关闭eslint 1. vue2创建脚手架项目 &#xff08;1&#xff09;在cmd窗口输入npm install -g vue/cli命令行&#xff0c;快速搭建脚手架。 &#xff08;2&#xff09; 创建vue2项目 &#xff08;3&#xff09; 选择配置项目&#xff0c…

前端学习篇一(HTML)

Introduction ##文章内容&#xff1a;使用HBuilder制作一个简单的HTML5网页以此达到学习HTML5 的目的 ##编写内容&#xff1a;1.HTML实现平台 2.HTML简介 3.HTML语言解析 ##编写人&#xff1a;贾雯爽 ##最后更新时间&#xff1a;2024/07/01 Overview Details 一、HTML简介…

骑行十里箐:风景,挑战与心灵,在幽谷中的协奏曲

2024年6月29日&#xff0c;星期六&#xff0c;一个看似平凡的日子&#xff0c;却因一次不同寻常的骑行而变得难以忘怀。作为校长骑行群的一员&#xff0c;我有幸参加了这次骑行十里箐的活动。从滇池后海的宁静开始&#xff0c;到宝珠山顶的壮观落幕&#xff0c;这一天的旅程充满…

本地Navicat/客户端连接阿里云RDSMySQL时遇到过的问题及解决

1.之前开发的RDS MySQL版本和本地MySQL版本最好接近&#xff0c;比如8.0.28和8.0.20好像都是可以兼容的&#xff0c;他们里面都有那个utf8的字符编码&#xff0c;但是后面我选的RDS MySQL版本有点新&#xff0c;是8.0.30甚至更新的版本&#xff0c;之前用C#语言写的连接MySQL以…

如何通过TPM活动提升员工的设备管理能力?

在快节奏的现代职场中&#xff0c;设备管理能力已成为员工综合素质的重要一环。然而&#xff0c;如何有效提升这一能力&#xff0c;让员工在设备操作、维护和管理上更加得心应手呢&#xff1f;答案就隐藏在TPM&#xff08;Total Productive Maintenance&#xff0c;全面生产维护…

嵌入式Linux系统编程 — 5.4 rand、srand 函数产生随机数

目录 1 随机数与伪随机数 2 rand和srand函数 3 示例程序 1 随机数与伪随机数 随机数在编程有广泛的应用场景&#xff0c;以下是一些常见的例子&#xff1a; 游戏开发&#xff1a;在电子游戏中&#xff0c;随机数用来决定各种事件的结果&#xff0c;如怪物的出现位置、敌人…

大会员体系是如何让积分流动起来,实现跨业态引流的?

积分&#xff0c;是大会员体系建设的重点&#xff0c;也是难点之一。 假设积分跨业态或者跨品牌流通&#xff0c;但没有一套统一的积分结算体系&#xff0c;就容易出现各业态或品牌利益分配不均的问题。 因此&#xff0c;大会员体系能有效落地的重点之一&#xff1a;集团必须…

【Week-G1】调用官方GAN实现MNIST数字识别,Pytorch框架

文章目录 1. 准备数据1.1 配置超参数1.2 下载数据1.3 配置数据 2. 创建模型2.1 定义鉴别器2.2 定义生成器 3. 训练模型3.1 创建实例3.2 开始训练3.3 保存模型 4. 什么是GAN&#xff08;对抗生成网络&#xff09;? &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学…

千益畅行,旅游卡,如何赚钱?

​ 赚钱这件事情&#xff0c;只有自己努力执行才会有结果。生活中没有幸运二字&#xff0c;每个光鲜亮丽的背后&#xff0c;都是不为人知的付出&#xff01; #旅游卡服务#

2024推荐整理几个磁力导航网站可提供海量资源的

都2024现在网上找资源像流水得鱼一样&#xff0c;抓一大把结果很难吃&#xff0c;我通宵特意整理的网站&#xff0c;网上有许多磁力导航网站可以提供海量的磁力链接资源&#xff0c;以下是一些有效的磁力导航网站推荐&#xff1a; 磁力搜索 链接&#xff1a; 资源类型&#x…

并发控制-事务的调度、数据不一致问题(更新丢失、脏读、不可重复读)、非串行调度的的可串行化

一、引言 1、数据库管理系统DBMS的事务处理技术实现的另一个主要功能部分是并发控制机制。并发控制机制完成的功能就是对并发执行的事务进行控制&#xff0c;保证事务的隔离性&#xff0c;从而进一步保持数据库的一致性。 2、事务的并发控制就是对并发执行的不同事务中的数据…

SpringMvc 执行原理

当用户请求 会发送到前端控制器&#xff0c;DisptcherServlet根据请求参数生成代理请求&#xff0c;找到对应的实际控制器&#xff0c;控制器处理请求&#xff0c;创建数据模型&#xff0c;访问数据库&#xff0c;将模型响应给中心控制器&#xff0c;控制器使用模型与视图渲染视…

前沿重器[52] | 聊聊搜索系统5:召回:检索、粗排、多路召回

前沿重器 栏目主要给大家分享各种大厂、顶会的论文和分享&#xff0c;从中抽取关键精华的部分和大家分享&#xff0c;和大家一起把握前沿技术。具体介绍&#xff1a;仓颉专项&#xff1a;飞机大炮我都会&#xff0c;利器心法我还有。&#xff08;算起来&#xff0c;专项启动已经…

KVM性能优化之CPU优化

1、查看kvm虚拟机vCPU的QEMU线程 ps -eLo ruser,pid,ppid,lwp,psr,args |awk /^qemu/{print $1,$2,$3,$4,$5,$6,$8} 注:vcpu是不同的线程&#xff0c;而不同的线程是跑在不同的cpu上&#xff0c;一般情况&#xff0c;虚拟机在运行时自身会点用3个cpus&#xff0c;为保证生产环…

EtherCAT笔记(五)—— 寻址方式与应用层协议

目录 1. EtherCAT 报文寻址 1.1 EtherCAT 网段寻址 1.1.1 直连模式 1.1.2 开放模式 1.2 段内寻址 —— 设备寻址 1.2.1 顺序寻址 1.2.2 设置寻址 1.3 逻辑寻址 1.4 关于WKC 2. 应用层协议 2.1 CoE &#xff1a; CANopen over EtherCAT 2.2 SoE (Servo Drive Profile …