首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

ES6系列Symbol数据类型

一. 概述

1. 基本含义

由于对象的属性名都是字符串,所以很容易出现属性名的冲突

在使用了某个别人的对象后,想给对象添加新的属性mixin模式,新属性的名字就可能和现有的属性发生冲突

Symbol数据类型的引入就是为了从根本上防止属性名冲突。

ES6中引入的Symbol数据类型表示独一无二的值,属于基本数据类型的一种

//?1.?使用Symbol函数生成

var?a=Symbol("foo")

console.log(a);//Symbol(foo)

console.log(typeof?a);//symbol

//?2.?使用new?Symbol会报错(因为没有包装对象,没有构造器函数)

var?b=new?Symbol("b");//TypeError:?Symbol?is?not?a?constructor

// 3. Symbol值即使参数一致,也不是同一个变量!

console.log(a===Symbol("foo"));//false

console.log(a==Symbol("foo"));//false

Symbol函数前不能使用new命令,否则会报错,这是因为Symbol值不是对象,只是类似字符串的数据类型,但是没有包装对象

Symbol值即使参数一致,也不是同一个变量!因为参数仅仅起到描述作用

2. 参数

如果Symbol可以有一个参数,表示该值的描述信息,也可以不添加该参数

如果参数是一个对象,那么就会调用该对象的toString()方法,将其转换为字符串,然后才生成Symbol值

//?1.没有参数

var?a=Symbol()

//?console.log(a);/Symbol()

//?2.?参数为字符串

var?b=Symbol("b")

//?console.log(b);//Symbol(b)

//?3.?参数为其他基本数据类型(先转换为字符串再转换为Symbol值,注意undefined会转为空)

var?c=Symbol(1);//Symbol(1)

//?var?c=Symbol(false);//Symbol(false)

//?var?c=Symbol(undefined);//Symbol()

//?var?c=Symbol(null);//Symbol(null)

var?c=Symbol(NaN);//Symbol(NaN)

console.log(c)

//?4.?参数为引用对象类型(即使无属性,也是Symbol([object?Object]))

var?d=Symbol({a:1})

console.log(d);//Symbol([object?Object])

var?e=Symbol({e:3,c:'ss'})

console.log(e);//Symbol([object?Object])

var?p=Symbol({})

console.log(p);//Symbol([object?Object])

//?5.定义对象的toString方法

var?obj={

toString(){

return?'我是自定义对象的方法'

}

}

console.log(Symbol(obj));//Symbol(我是自定义对象的方法)

3. 转换

Symbol值不能和其他值进行运算,会报错!

Symbol值可以转换为字符串,通过toString()或者String()

Symbol值也可以转为布尔值,但是不可以转为数值

//?1.Symbol运算

//?console.log(Symbol(1)+Symbol(2));//Cannot?convert?a?Symbol?value?to?a?number

//?console.log(Symbol(1)+1);//Cannot?convert?a?Symbol?value?to?a?number

//?console.log("i?am"+Symbol("ww"));//Cannot?convert?a?Symbol?value?to?a?string

//?2.Symbol值可以显式转为字符串

console.log(String(Symbol("2")));//Symbol(2)

console.log(Symbol("ss").toString());//Symbol(ss)

//?3.Symbol值可以转为布尔值

console.log(Boolean(Symbol(1)));//true

//?4.Symbol值不能转为数值

console.log(Number(Symbol(1)));//Cannot?convert?a?Symbol?value?to?a?number

二. Symbol描述

虽然可以通过String(),toString()来获取Symbol值的描述,但是会带有Symbol()前缀

ES2019提供了description属性来直接返回描述console.log(Symbol("foo").description);//foo

三. Symbol作为属性名

Symbol常常用于作为属性名,防止属性被覆盖!

1.有以下三种用法

var?a=Symbol("foo")

//?1.

//?var?obj={}

//?obj[a]="ww";

//?console.log(obj[a]);//ww

//2

/*??var?obj={

[a]:"ww"

}

console.log(obj[a]);//ww?*/

//3.Object.defineProperty(),不设置enumerable的话,定义的属性默认是不可枚举的

var?obj={}

Object.defineProperty(obj,a,{value:"ww"})

console.log(obj[a]);//ww

//{value:?"ww",?writable:?false,?enumerable:?false,?configurable:?false}

console.log(Object.getOwnPropertyDescriptor(obj,a));

2.注意事项

如果属性a属于Symbol类型,那么不能使用obj.a 形式!因为会被识别为字符串

var?a=Symbol()

var?obj={}

//?1.?使用点运算符,后面的变量被视为字符串

obj.a="ss"

console.log(obj.a);//ss

//?2.?使用中括号形式

obj[a]="hello"

console.log(obj[a]);//hello,此时指向的是Symbol类型的变量

console.log(obj.a);//ss,此时指向的是a这个属性!

作为对象方法使用

//?1.相当于属性

var?a=Symbol()

var?obj={

[a]:function(){?return?1}

}

console.log(obj[a]());//1

//2.对象方法

let?b={

[a](){

return?2

}

}

console.log(b[a]());//2

四. 消除魔术字符串

魔术字符串就是在代码中多次出现,和代码形成强耦合的字符串,应该尽量消除魔术字符串,改用变量代替

使用Symbol消除的一个例子

//?1.?存在魔术字符串时

function?getData(str,options){

var?res;

switch(str){

case?"str":

res=?options.a+options.b;

}

return?res;

}

console.log(getData("str",{a:3,b:2}));//?str这个字符串形成了强耦合

//?2.?使用Symbol解决

var?a={

e:Symbol()

}

function?tryData(str,options){

var?res;

switch(str){

case?a.e:

res=?options.a+options.b;

}

return?res;

}

console.log(tryData(a.e,{a:3,b:2}))

五.Symbol属性名的遍历

for...in;for...of循环;Object.keys(),Object.values(),Object.entries();Object.getOwnPropertyNames();JSON.stringfy()都不会出现Symbol属性名

Object.getOwnPropertySymbols()方法可以获取到对象的所有Symbol属性名,但是不能获取到除了Symbol之外的属性

另外Reflect.ownKeys()可以获取到所有类型的键名,包括Symbol,不可枚举

var?obj={a:1,1:'e',3:'y',b:99}

obj[Symbol('q')]='symbol'

obj[Symbol('p')]='p'

//1.for?in,for...of

for(var?item?in?obj){

console.log(item);//1,3,a,b

}

//?obj?is?not?iterable?报错

//?for(var?item?of?obj){

//??console.log(item)

//?}

//2.JSON.stringfy

console.log(JSON.stringify(obj));//{"1":"e","3":"y","a":1,"b":99}

//3.?Object.getOwnPropertySymbols

console.log(Object.getOwnPropertySymbols(obj));//[Symbol(q),?Symbol(p)]

//4.?Reflect.ownkeys()

console.log(Reflect.ownKeys(obj));//["1",?"3",?"a",?"b",?Symbol(q),?Symbol(p)]

六.Symbol.for()和Symbol.keyFor()

有时我们需要知道是否存在该名称的Symbol变量,或者进行修改,但是直接使用Symbol()会新增一个变量

1. Symbol.for()

使用Symbol.for()可以接受一个字符串作为参数,然后搜索是否存在使用过Symbol.for()的同名变量

//?1.?Symbol,还有一个Symbol.for

var?a=Symbol('a')

var?aa=Symbol.for('a')

console.log(a===aa);//false

//2.?两个都是用了Symbol.for()

var?b=Symbol.for('b')

var?bb=Symbol.for('b')

console.log(b===bb);//true

//3.?空参数

var?c=Symbol.for()

var?cc=Symbol.for()

console.log(c===cc);//true

当不存在同名Symbol.for()定义的方法时,定义之后会注册到全局中

而使用Symbol()方法不会把变量注册到全局中!

2. Symbol.keyFor()

Symbol.keyFor()可以返回已在全局注册(Symbol.for())的Symbol类型的参数名

并且Symbol.for()即使在函数中,也是把变量注册到全局的

//?1.?Symbol.keyFor()

var?s1=Symbol.for('a')

var?s2=Symbol('b')

console.log(Symbol.keyFor(s1));//a

console.log(Symbol.keyFor(s2));//undefined,没有在全局注册

//?2.在函数中使用Symbol.for()也是注册到全局中

function?func(){

return?Symbol.for('bar')

}

var?x=func();//?注册bar到全局了

var?y=Symbol.for('bar')

console.log(x===y);//true

七. Symbol的一些方法

1. Symbol.hasInstance()

foo instanceof MyClass相当于 MyClass[Symbol.hasInstance](foo)

class?MyArray{

static?[Symbol.hasInstance](instance){

return?Array.isArray(instance)

}

}

console.log([1]?instanceof?MyArray);//true,static静态属性才能被类直接使用,去掉则false

2. Symbol.match()

对象的Symbol.match属性指向一个函数,当执行str.match(obj)的时候该属性存在则调用,返回方法的返回值

str.match(func),相当于 [symbol.macth](str)

//?使用方法一:使用类的实例

class?MyClass{

[Symbol.match](str){

return?'字符串'

}

}

console.log("hello?blog".match(new?MyClass()));//字符串

//?方法二;使用对象属性

var?obj={

[Symbol.match](str){

return?str;

}

}

console.log('hhha'.match(obj));//hhha

3. Symbol.iterator()

只要调用...拓展运算符,那么相当于执行了对象里面存在[Symbol.iterator]方法

var?obj={

*?[Symbol.iterator]()?{

yield?1;

yield?2;

yield?3;

}

}

console.log([...obj]);//[1,?2,?3]

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200612A007F000?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com