Symbol

news/2024/7/24 4:27:40 标签: javascript, 前端, vue.js

Symbol是ES6新增的一种基本数据类型 它用来表示独一无二的值, 通过Symbol函数生成
Symbol前面不能加new ,创建symbol类型指的时候传入一个参数,这个参数需要是字符串
使用Symbol函数创建一个symbol类型值,可以给它传入一个字符串参数,来对symbol值所一个区分,但是即使多次Symbol函数调用,传入的是相同的字符串,创建的symbol值也是彼此不同的

javascript">var s = Symbol('keke')
可转为string或布尔类型的值
s.toString()//Symbol(keke)
Boolean(s)//true

可作为属性名

javascript">var s = Symbol()
console.log(s);
let obj = {
  [s]:'kekek'
}
console.log(obj); //{Symbol(): 'kekek'}
console.log(obj[s]);//keke

访问到Symbol类型的属性名

javascript">var s = Symbol("name")
let obj = {
  [s]: 'kke',
  age: 12
}
for(var key in obj){
  console.log(key);//age
}
console.log(Object.keys(obj));//['age']
console.log(Object.getOwnPropertyNames(obj)); //['age']
console.log(JSON.stringify(obj)); //{"age":12}

虽然这么多方法都无法遍历访问到Symbol类型的属性名,但是Symbol类型的属性并不是私有属性,我们可以使用

javascript">Object.getOwnPropertySymbols方法获取对象的所有symbol类型的属性名
let SymbolProNames = Object.getOwnPropertySymbols(obj)
console.log(SymbolProNames);//[Symbol(name)]

可取到Symbol属性名对应的值
console.log(obj[SymbolProNames[0]]); //kk

除了Object.getOwnPropertySymbols这个方法,还可以用ES6提供的Reflect对象的静态方法 Reflect.ownKeys,它可以返回所有类型的属性名,所以Symbol类型的也会返回

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

Symbol.for()和Symbol.keyFor()

Symbol包含两个静态方法 for和keyFor

javascript">const s1 = Symbol('pp')
const s2 = Symbol('pp')
const s3 = Symbol.for('pp')
const s4 = Symbol.for('pp')
s1===s2//false
console.log(s3===s4)//true
console.log(s1==s3);//false
  • 直接使用Symbol方法,即便传入的字符串是一样的,创建的symbol值也是互不相等的,
  • 而使用Symbol.for方法传入字符串会先检查有没有使用该字符串调用Symbol.for方法创建的symbol值,如果有直接返回该值,如果没有,则使用该字符串创建一个。
  • 使用该方法创建symbol值后会在全局范围内进行注册。注意:这个注册的范围包括当前页面和页面中包含的iframe,以及service sorker
javascript">const iframe = document.createElement('iframe')
iframe.src = String(window.location)
document.body.appendChild(iframe)
iframe.contentWindow.Symbol.for("lison")=== Symbol.for("lison") //true

上面的这段意思是 创建一个iframe节点并把它放到body中,我们通过这个iframe对象的contentWindow拿到这个iframe的window对象
在iframe.contentWindow上添加一个值就相当于你在当前页面定义一个全局变量一样

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

javascript">const sym = Symbol.for('ook')
console.log(Symbol.keyFor(sym));//ook

11个内置symbol值

Symbol.hasInstance

对象的Symbol.hasInstance 指向一个内部方法 当你给一个对象设置以Symbol.hasInstance为属性名的方法后,
当其他对象使用instanceof 判断是否为这个对象的实例时,会调用你定义的这个方法 参数是其他的这个对象

javascript">const obj ={
  [Symbol.hasInstance](otherObj){
    console.log(otherObj); //{a: 'a'}
  }
}
console.log({a:'a'} instanceof obj)//false
instanceof 运算符用于该对象的prototype属性是否出现在某个实例对象的原型链上
  • 注意: 在TypeScript中这会报错, instanceof表达式的右侧必须属于类型 “any”,或属于分配给 "Function"接口类型的类型
  • 是要求你instanceof操作符右侧的值只能是构造函数或者类 或者类型any类型 这里你可以使用类型断言 将obj改为obj as any

Symbol.isConcatSpreadable

这个值是一个可读写布尔值,当一个数组的Symbol.isConcatSpreadable设置为false时,这个数组在数组的concat方法中不会被扁平化。

javascript">let arr = [1,2,3]
console.log([].concat(arr,[4,5]));
let arr1 = ['a','b']
console.log(arr1[Symbol.isConcatSpreadable]);//undefined
arr1[Symbol.isConcatSpreadable] = false
console.log(arr1[Symbol.isConcatSpreadable]);//false
console.log([].concat(arr1,arr));// [ ["a", "b", Symbol(Symbol.isConcatSpreadable): false], 1, 2,3 ]

因为我们设置了Symbol.isConcatSpreadable为false,所以第一个数组没有被扁平化,第一个数组中的 Symbol(Symbol.isConcatSpreadable): false
不是他的元素 而是他的属性 因为数组也是对象,所以也可以给数组设置属性

javascript">arr.props = "value"
console.log(arr);//[1, 2, 3, props: 'value']

Symbol.species

使用class定义一个类C, 使用extends继承原生构造函数Array,那么类C创建的实例就能继承所有Array原型对象上的方法,比如map,filter

javascript">class C extends Array{
  getName(){
    return "Ok"
  }
}
const c = new C(1,2,3)
console.log(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());//Ok

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

javascript">class C extends Array{
  static get[Symbol.species](){
    return Array
  }
  getName(){
    return "pp"
  }
}
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);//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、 Symbol.search、Symbol.replace、和Symbol.split

这个Symbol.match值指向一个内部方法 当字符串Str 调用match方法时 ,会调用这个方法
match() 方法检索返回一个字符串匹配正则表达式的结果

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

同样的还有Symbol.replace 、 Symbol.search,使用方法和Symbol.match是一样的

Symbol.iterator

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

javascript">const arr = [1,2,3]
const interator = arr[Symbol.iterator]()
console.log(interator);
console.log(interator.next());//{value: 1, done: false}
console.log(interator.next());//{value: 2, done: false}
console.log(interator.next());//{value: 3, done: false}

这个Symbol.iterator方法是可写的,我们可以自定义遍历器方法

Symbol.toPrimitive

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

javascript">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这个值:

javascript"> let obj = {
   [Symbol.toStringTag]:'kkk'
 }
console.log(obj.toString());//[object kkk]

Symbol.unscopables

这个值和with命令相关 我们先来看with怎么使用

javascript"> const obj = {
   a:'a',
   b:'b'
 }
with(obj){
  console.log(a);//a
  console.log(b);//b
}

可以看到 使用with传入一个对象后 在代码块中访问对象的属性就不需要写对象了,直接使用它的属性 对象的Symbol.unscopables
属性指向一个对象,该对象包含了当使用with关键字时,哪些属性被with环境过滤掉

javascript">console.log(Array.prototype[Symbol.unscopables]);
{
  copyWithin: true
  entries: true
  fill: true
  find: true
  findIndex: true
  includes: true
  keys: true
  values: true
}

在Ts中使用Symbol类型

javascript">let sym:symbol = Symbol()

unique symbol

ts在2.7版本对Symbol做了补充,增加了 unique symbol这种类型, 他是symbol的子类型 这种类型的值只能由Symbol()活Symbol.for()创建
或者通过指定类型来指定一个值是这种类型 这种类型的值仅可用于常量的定义和用于属性名。另外定义unique symbol类型的值
必须用const 不能let

javascript">const key1:unique symbol = Symbol()
let key2:symbol = Symbol()
let obj={
  [key1]:'value1',
  [key2]:'value2'
}
console.log(obj[key1]);
console.log(obj[key2]);//error类型symbol不能作为索引类型使用

http://www.niftyadmin.cn/n/119839.html

相关文章

GVRP-LNP-VCMP讲解

目录 GVRP讲解 动态创建Vlan并将端口加入Vlan GVRP消息类型 GVRP工作原理 LNP讲解 动态修改接口链路类型 VCMP讲解 动态创建Vlan 相关概念 Vlan同步 VCMP与GVRP的区别 GVRP讲解 动态创建Vlan并将端口加入Vlan GVRP(GARR Vlan Registration Protocol&#xf…

前端安全(http)

前端安全XSS 攻击CSRF 防范输入不检验可能引发a 标签的 <font colororange> window 跳转 和 a 标签跳转Dos 拒绝服务JSONXSS 攻击 cross site script 跨站脚本攻击 会导致: 会话劫持, 钓鱼, 信息泄露 , 不会导致拒绝服务 可能引起: setTimeout , new Function, eval ,en…

Spring Boot结合IDEA自带Maven插件快速切换profile | Spring Cloud 10

一、前言 IDEA是目前 Java 开发者中使用最多的开发工具&#xff0c;它有着简约的设计风格&#xff0c;强大的集成工具&#xff0c;便利的快捷键。 在项目项目整个开发运维周期中&#xff0c;我们的的项目往往需要根据不同的环境&#xff0c;使用不同的文件配置。 比如以下部…

MySQL——复合查询+表的内外连接

文章目录复合查询基本查询多表查询自连接子查询1、单行子查询2、多行子查询3、多列子查询4、在from子句中使用子查询&#x1f60a;5、合并查询结果unionunion all表的内连和外连内连接外连接左外连接右外连接复合查询 接下来我们就要进行的是多张表里进行查询操作&#xff0c;…

【2021.12.25】ctf逆向中常见加密算法和编码识别

【2021.12.25】ctf逆向中常见加密算法和编码识别&#xff08;含exe及wp&#xff09; 文章目录【2021.12.25】ctf逆向中常见加密算法和编码识别&#xff08;含exe及wp&#xff09;0、前言1、基础加密手法2、base64&#xff08;1&#xff09;原理&#xff1a;&#xff08;2&#…

通信网络-Socket、Java中的网络支持、多线程服务器

前言 通信网络-Socket、Java中的网络支持、多线程服务器 场景&#xff1a;使用java网络创建一个聊天室 博客地址&#xff1a;芒果橙的个人博客 文章目录前言通信网络-SocketTCP/IPTCP/IP 模型端口Java中的网络支持概念1. InetAddress2. URL3. Socket4. Datagram多线程服务器应用…

PyQGIS自定义应用程序打包

路径准备ps:打包时需要根据自己的安装路径进行相应修改QGIS3.22.16的安装路径&#xff1a;D:\QGIS3.22.16QGIS3.22.16中python-qgis.bat的路径&#xff1a;D:\QGIS3.22.16\bin\python-qgis-ltr.bat准备打包的工程所在目录&#xff1a;E:\Crater_DamageEstimation0303安装pyinst…

【truncate、delete和drop的6大区别!】

在MySQL中&#xff0c;truncate、delete和drop是三个常用的命令&#xff0c;它们可以用于删除表或表中的数据&#xff0c;下面是它们的六大区别&#xff1a; 语法不同&#xff1a; truncate和delete是SQL语句&#xff0c;drop是DDL&#xff08;数据定义语言&#xff09;语句。…