<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在前文《JavaScript的8种资料型别》中,我们已经简单的介绍过了JavaScript
的Symbol
型别,下面对其使用方法和使用场景做一个简单的介绍。
Symbol
型别是JavaScript
中的一种特殊的型别,特殊在所有的Symbol
型别值都互不相同。我们可以使用“Symbol”来表示唯一的值,下面是建立Symbol
物件的案例:
let id = Symbol();
这样我们就建立了一个Symbol
型别的值,并把这个值储存在了变数id
中。
我们在建立一个Symbol
型别变数的时候,可以在引数中传入一些秒属性的字串,用于描述这个变数的用途资讯。
例如:
let id1 = Symbol('狂拽酷炫吊炸天的小明的id'); let id2 = Symbol('低调奢华有内涵的婷婷的id');
Symbol
型别在任何时候都是不同的,即使他们拥有相同的描述资讯,描述只是一个标签,除此之外就没有别的用途了,例如:
let id1 = Symbol('id'); let id2 = Symbol('id'); console.log(id1==id2);//false
这个标签存在的意义,个人认为和Symbol
不能直观的看到内部具体值的特性有关,通过新增一个描述资讯,让我们对变数的用途有更直观的了解。
JavaScript
中的大多数型别都可以直接转换成字串型别输出,所以我们不能直观的看到它的值到底是什么,例如我们可以直接用alert(123)
把数位123
转换成字串弹出。
但是Symbol
型别比较特殊,它不能直接转换,例如:
let id = Symbol(); alert(id);//报错,不能把Symbol型别转为字串
JavaScript
中的Symbol
型别不能转成字串是由于其内在的防治语言混乱的“语言保护”机制,因为字串和Symbol
在本质上有着区别,不应该将其中一个转换成另一个。
试想一下,如果Symbol
可以转为字串,那么它就变成了一个生成独一无二字串的函数,就不再具备独立资料型别的必要。
如果我们真的想知道Symbol
变数的值,我们可以使用.toString()
方法,如下所示:
let id = Symbol('this is identification'); console.log(id.toString());//Symbol(this is identification);
或者使用.description
属性,获取描述资讯:
let id = Symbol('加油,奥利给'); console.log(id.description);//加油,奥利给」
根据JavaScript
的规范,只有两种型别的值可以作为物件的属性键:
如果使用其他型别,则会隐式的转为字串型别。物件的键在前面的章节有详细的介绍,这里不再重复。
将Symbol
作为键值有两种方法:
例1:
let id = Symbol('id'); let user = {}; user[id] = 'id value';//新增Symbol键 console.log(user[id]);//id value
例2:
let id = Symbol('id'); let user = { [id]:'id value',//注意这里的方括号 }; console.log(user[id]);
以上两个案例展示了在物件中插入Symbol
型别作为键的用法,需要注意的是,在存取属性时需要使用obj[id]
而不是obj.id
,因为obj.id
代表的是obj[‘id’]
。
如果我们使用Symbol
作为物件的键会有什么效果呢?
Symbol
非常明显的一个特征是,如果物件中使用Symbol
作为键,那么使用for…in
语句是存取不到Symbol
型别的属性的。
举个例子:
let id = Symbol('id'); let user = { name : 'xiaoming', [id] : 'id', }; for (let key in user) console.log(user[key]);
执行以上程式码,得到以下结果:
> xiaoming
可以发现,[id]
物件的值没有被列印出来,说明在物件属性列表中,使用for … in
会自动忽略Symbol
型别的键。
同样的,Object.keys(user)
也会忽略所有的Symbol
型别的键。
这样的特效能带来非常有用的效果,例如我们可以建立只能自己能用的属性。
虽然我们没有办法直接获取到Symbol
键,但是Object.assign
方法能够复制所有的属性:
let id = Symbol(); let obj = { [id] : '123' } let obj2 = Object.assign({},obj); console.log(obj2[id]);
这并不影响Symbol
的隐藏属性,因为复制后的物件仍然无法获取Symbol
键。
由于Symbol
既不能直接转为字串,我们没有办法直观的获得它的值,又不能通过for … in
获得物件的Symbol
属性,也就是说,如果没有Symbol
变数本身,我们就没有办法获得物件内部的对应属性。
因此,通过Symbol
型别的键值,我们可以隐藏属性,这些属性只能我们自己存取,其他人都看不到我们的属性。
举个例子:
我们在开发的过程中,需要和同事“张三”合作,而这个张三建立了一个非常好用的工具Tool
,Tool
是一个物件型别,我们想白嫖张三的Tool
,并在此基础上新增一些自己的属性。
我们就可以通过新增Symbol
型别的键:
let tool = {//张三写好了的Tool usage : "Can do anything", } let name = Symbol("My tool obj"); tool[name] = "This is my tool"; console.log(tool[name]);
以上范例展示了如何在别人写好的物件上新增自己的属性,那么为什么要使用Symbol
型别而不是常规的字串呢?
原因如下:
tool
是别人写好的程式码,原则上我们不应该去修改别人的程式码,这样会造成风险;Symbol
永远不会发生命名冲突,因为Symbol
都是不同的;Symbol
型别的键,相当于不会和别人的程式码冲突;错误示范:
如果我们不使用Symbol
型别,很可能出现以下情况:
let tool = {//张三写好了的Tool usage : "Can do anything", } tool.usage = "Boom Boom"; console.log(tool.usage);
以上程式码由于重复使用”usage”,从而重写了原属性,会造成物件原功能异常。
所有的Symbol
变数都是不同的,即使他们有用相同的标签(描述)。
有些时候,我们希望通过一个字串名称(标签),存取同一个Symbol
物件,例如我们在程式码的不同地方存取相同的Symbol
。
JavaScript
会维护一个全域性的Symbol
登录档,我们可以通过向登录档中插入Symbol
物件,并为物件起一个字串名称存取该物件。
向登录档插入或者读取Symbol
物件需要使用Symbol.for(key)
方法,如果登录档中有名为key
的物件,就返回该物件,否则就插入新物件再返回。
举个例子:
let id1 = Symbol.for('id');//登录档内没有名为id的Symbol,建立并返回 let id2 = Symbol.for('id');//登录档内已有名为id的Symbol,直接返回 console.log(id1===id2);//true
我们通过Symbol.for(key)
就能以全域性变数的方式使用Symbol
物件,并使用一个字串标记物件的名字。
相反的,我们还可以使用Symbol.keyFor(Symbol)
反向的从物件获取名称。
举个例子:
let id = Symbol.for('id');//登录档内没有名为id的Symbol,建立并返回 let name = Symbol.keyFor(id); console.log(name);//id
Symbol.keyFor()
函数只能用在全域性Symbol
物件上(使用Symbol.for
插入的物件),如果用在非全域性物件上,就会返回undefined
。
举个例子:
let id = Symbol('id');//区域性Symbol let name = Symbol.keyFor(id); console.log(name);//undefined
JavaScript
有许多系统Symbol
,例如:
Symbol.hasInstance
Symbol.iterator
Symbol.toPrimitive
它们各有用途,我们在后面的会逐步介绍道这些独特的变数。
Symbol
物件的值是唯一的;Symbol
可以新增一个标签,并通过标签在全域性登录档中查询物件的实体;Symbol
作为物件的键无法被for … in
探测到;Symbol
到全域性登录档存取全域性的Symbol
物件;但是,Symbol
并不是完全隐藏的,我们可以通过Object.getOwnPropertySymbols(obj)
获取物件所有的Symbol
,或者通过Reflect.ownKeys(obj)
获取物件所有的键。
到此这篇关于JavaScript的Symbol型别、隐藏属性、全域性登录档的文章就介绍到这了,更多相关js Symbol型别、隐藏属性、全域性登录档内容请搜寻it145.com以前的文章或继续浏览下面的相关文章希望大家以后多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45