JavaScript中原始数据类型Symbol如何使用
导读:本文共4944.5字符,通常情况下阅读需要16分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要: SymbolSymbol是es6引入的一个新的原始数据类型,是一个独一无二的值。目前为止,js的数据类型有以下几种:数据类型说明undefinedundefinednullnullboolean布尔值string字符串number数字Bigint大整数Object对象SymbolSymbolSymbol通过Symbol()函数生成。对象的属性名现在除了可以使用字... ...
目录
(为您整理了一些要点),点击可以直达。Symbol
Symbol
是es6
引入的一个新的原始数据类型,是一个独一无二
的值。
目前为止,js
的数据类型有以下几种:
Symbol
通过Symbol()
函数生成。对象的属性名现在除了可以使用字符串以外,还可以使用新增的Symbol
类型。如果属性名使用Symbol
,那么它就是独一无二的,不与其它属性名产生冲突。
lets=Symbol()console.log(typeofs);//symbol
注意:Symbol()
函数前不能使用new
,否则报错。因为生成的Symbol
是一个原始类型的值,而不是对象,所以不能使用new
来调用。而且,Symbol
值不是对象,不能给Symbol
添加属性。可以这么理解,Symbol
是一种类似于字符串的数据类型。
Symbol
接收字符串作为参数,表示对Symbol
的描述,添加描述可以用来区分多个Symbol
。
lets2=Symbol('desc')lets3=Symbol('desc2')console.log(s2);//Symbol(desc)console.log(s3);//Symbol(desc2)
如果Symbol
的参数传入的是对象,需要把对象转为字符串再生成Symbol
,否则会显示[object Object]
。
letobj={name:'东方不败'}lets4=Symbol(JSON.stringify(obj))console.log(s4);//Symbol({"name":"东方不败"})lets5=Symbol(obj)console.log(s5);//Symbol([objectObject])
Symbol
传入的参数只是一个描述,实际上Symbol
和Symbol
并不相等。
letsy=Symbol()letsy2=Symbol()console.log(sy===s2);//falseletsy3=Symbol('a')letsy4=Symbol('a')console.log(sy3===sy4);//false
每调用一次Symbol()
都会生成一个独一无二的值,每个Symbol
都不相等。
Symbol
值不能参与其他类型值的运算,否则报错。
leta=Symbol('hello')console.log(a+'world');//报错CannotconvertaSymbolvaluetoastring
Symbol转换
Symbol可以转换为字符串
leta2=Symbol('hello')console.log(String(a2));//Symbol(hello)
如果需要返回Symbol
的描述需要使用es2019
提供的Symbol
实例属性description
返回描述。
leta2=Symbol('hello')console.log(a2.description);//hello
Symbol可以转换为布尔值(boolean)
leta2=Symbol('hello')console.log(Boolean(a2));//trueconsole.log(Boolean(!a2));//false
Symbol属性名
Symbol
作为属性名
letn=Symbol()//方式一letobj2={[n]:'东方不败'}console.log(obj2);//{Symbol():'东方不败'}console.log(obj2[n]);//东方不败//方式二obj2[n]='东方求败'console.log(obj2[n]);//东方求败//方式三letobj3={}letback=Object.defineProperty(obj3,n,{value:'艺术概论'})console.log(obj3[n]);//艺术概论
Object.defineProperty
使用说明
第一个参数:要在其上定义属性的对象
第二个参数:要定义或修改的属性的名称
第三个参数:将被定义或修改的属性描述符
Symbol
值作为对象属性名时,不能用点运算符
获得Symbol
属性,使用点运算符相当于是给对象添加了一个字符串属性名
,而不是获取Symbol
。
letn2=Symbol()letobj4={}console.log(obj4.n2='中国工艺美术史');//中国工艺美术史console.log(obj4[n2]);//undefinedconsole.log(obj4);//{n2:'中国工艺美术史'}
属性名遍历
Symbol
是不可枚举的,Symbol
作为对象键名时,是不可被遍历的,for...in
、Object.keys
等方法都得不到Symbol
键名,并且JSON.stringify()
也不会返回Symbol
。
letm=Symbol('a')letf={[m]:'东方不败',name:'西方求败',name2:'光合作用'}//西方求败、光合作用for(kinf){console.log(f[k]);}console.log(Object.keys(f));//['name','name2']console.log(JSON.stringify(f));//{"name":"西方求败","name2":"光合作用"}
Reflect.ownKeys()
可以返回常规键名和Symbol
键名
console.log(Reflect.ownKeys(f));//['name','name2',Symbol(a)]
Object.getOwnPropertySymbols()
只返回Symbol
属性
console.log(Object.getOwnPropertySymbols(f));//[Symbol(a)]
Symbol.for()、Symbol.keyFor()
Symbol.for()Symbol
有一个特性就是Symbol
不等于Sombol
,但有时候我们需要同一个Symbol
值
letr=Symbol.for('a')letr2=Symbol.for('a')console.log(r===r2);//true
Symbol.for()
和Symbol()
都会生成新的Symbol
,前者会被登记在全局环境提供搜索,后者不会。
Symbol.for()
每次调用都会先检查参数key
是否存在,如果不存在才会新建一个值。
Symbol()
每次调用都会新建一个值。
Symbol.keyFor()Symbol.keyFor()
返回已经登记的Symbol
值的key
letr3=Symbol.for('b')letr4=Symbol('c')console.log(Symbol.keyFor(r3));//bconsole.log(Symbol.keyFor(r4));//undefined
Symbol内置值
Symbol.hasInstance
Symbol.hasInstance
用来判断某个对象是否为某个构造器实例
classmyClass{static[Symbol.hasInstance](val){returntypeofval==='number'}//static[Symbol.hasInstance](val){//returntypeofval==='boolean'//}}console.log(100instanceofmyClass);//trueconsole.log('100'instanceofmyClass);//false
多个Symbol.hasInstance
会覆盖,只保留最下面的那一个。
Symbol.isConcatSpreadable
Symbol.isConcatSpreadable
用于表示Array.prototype.concat()
是否可以展开,true、undefined
可以展开,false
不可展开。
letarr1=[1,2]letarr2=[3,4]console.log(arr1[Symbol.isConcatSpreadable]);//undefinedconsole.log(arr1.concat(arr2));//[1,2,3,4]
console.log(arr1[Symbol.isConcatSpreadable]=false)console.log(arr1.concat(arr2));//[[1,2],3,4]
Symbol.species
对象的Symbol.species
属性指向一个构造函数,创建衍生对象时会使用该属性
//这里继承了Array的原型classMyArrayextendsArray{}leta=newMyArray(1,2,3)letb=a.map(el=>el+1)console.log(b);//constructor:classMyArray
b
和c
调用的是数组方法,那么应该是Array
的实例,但实际上它们也是MyArray
的实例
classMyArrayextendsArray{staticget[Symbol.species](){returnArray}}leta=newMyArray(1,2,3)letb=a.map(el=>el+1)letc=a.filter(el=>el==2)console.log(a,b,c);//1,2,32,3,42console.log(binstanceofMyArray);//falseconsole.log(b);//constructor:classMyArray
Symbol.species
可以在创建衍生对象时使用这个属性返回的函数作为构造函数。
这里return
了Array
,所以创建的衍生对象使用的Array
作为构造函数,而不是MyArray
。
如果这里return
一个String
,那么上面的map、filter
会报错,因为衍生对象使用的是String
作为构造函数,String
是没有数组方法的。
Symbol.match
Symbol.match
指向一个函数,如果函数存在则会被调用,并返回该方法的返回值
classMyMatch{[Symbol.match](val){return'helloworld'.indexOf(val)}}//match字符串方法,可以在字符串内检索指定的值并返回console.log('e'.match(newMyMatch()));//1
</div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
JavaScript中原始数据类型Symbol如何使用的详细内容,希望对您有所帮助,信息来源于网络。