当前位置: 首页 > Web前端 > HTML

符号类型使用介绍

时间:2023-03-29 12:25:50 HTML

前言ES6更新了第七种基本数据类型符号,也称为符号类型,用作全局唯一指示符。并且以Symbol静态属性的形式,将可以修改JS内部语言行为的方法暴露给前端开发者,以便对对象进行更深层次的操作。声明方法可以通过调用全局Symbol函数得到一个symbol类型的变量,可以传递一个string类型的参数来表示这个symbol的描述,可以通过description属性访问,但是这两个描述是同一个symbol,不相等。constsy=Symbol('Descriptionofsymbol')console.log(sy)//Symbol(Descriptionofsymbol)console.log(sy.description)//'Descriptionofsymbol'constsy2=Symbol('Descriptionofsymbol')console.log(sy2===sy)//falseconsole.log(sy2.description===sy.description)//真实符号描述的意义只是方便开发者调试,没有办法获取其相应的符号。Symbol作为构造函数并不完整,所以不支持语法:newSymbol()globalsymbolregistrySymbol有两个静态方法维护一个全局的symbolregistry(可以看做是一个Map),实现symbol描述和描述之间的转换描述。Symbol.for也可以创建一个符号,也可以接受一个字符串作为符号的描述。并将此符号添加到全局注册表中。如果下次通过该方法创建一个描述相同的品种,则直接返回创建的品种。Symbol.keyFor检查符号是否在全局注册表中注册,如果是,则返回其描述。说实话,这两种方式在实际开发中是完全没有用到的,也没有必要将符号和描述相互转换,但是为了内容的完整性,我还是简单介绍一下。Symbol的静态属性Symbol有很多静态属性,开发者可以通过配置它们来改变JS的内部语言行为。下面介绍三种比较常用的。Symbol.iterator,用于为对象定义一个迭代器,它的值应该是一个生成器函数。在下面的扩展遍历部分,会用到这个属性来大大扩展for的功能。Symbol.toStringTag,用来修饰对象的字符串标签,它的值应该是一个函数,函数的返回值是一个字符串,一般用来区分类的实例。Symbol.toPrimitive,用于定义对象转换为原始值时的行为,接受一个表示转换倾向的参数。详见引用数据类型转换规则Symbol还有很多静态方法,一般开发中很少用到,这里不再介绍。使用场景Symbol一般用于以下场景,定义类标签。可以为类配置Symbol.toStringTag属性,很容易得到对象所属的类标签。使用switch匹配比使用instanceof比较方便,反复尝试。类模式{get[Symbol.toStringTag](){return'Pattern'}}classEnvelope{get[Symbol.toStringTag](){return'Envelope'}}constpattern=newPattern()constenvelope=newEnvelope()console.log(Object.prototype.toString.call(pattern))//'[objectPattern]'console.log(Object.prototype.toString.call(envelope))//'[objectEnvelope]'当然,你也可以不依赖Object.prototype.toString方法,直接通过类中的其他属性来定义它的类型。类模式{getclassType(){return'Pattern'}}classEnvelope{getclassType(){return'Envelope'}}constpattern=newPattern()constenvelope=newEnvelope()console.log(pattern['classType'])//'Pattern'console.log(envelope['classType'])//'Envelope'消除了魔法字符串。魔法字符串是指在代码中出现多次,与代码形成强耦合的字符串。具体字符串。在风格良好的代码中,应尽可能消除魔术字符串。下面的例子中,classType、Envelope、Pattern是魔术字符串,多次出现,与代码形成“强耦合”,不利于以后的修改和维护。classPattern{getclassType(){return'Pattern'}}classEnvelope{getclassType(){return'Envelope'}}functiondrawItem(item){consttype=item['classType']开关(类型){case'Pattern':breakcase'Envelope':break}}functiondeleteItem(item){consttype=item['classType']switch(type){case'Pattern':breakcase'Envelope':break}}常用消除法术string的方法是把它写成一个变量。我们不关心这个变量的值是什么,我们只需要它是全局唯一的,符号类型在这里就完美了。constCLASS_TYPE=Symbol('classType')constPATTERN=Symbol('Pattern')constENVELOPE=Symbol('Envelope')classPattern{get[CLASS_TYPE](){返回PATTERN}}classEnvelope{get[CLASS_TYPE](){returnENVELOPE}}functiondrawItem(item){consttype=item[CLASS_TYPE]switch(type){casePATTERN:breakcaseENVELOPE:break}}functiondeleteItem(item){consttype=item[CLASS_TYPE]开关(类型){casePATTERN:breakcaseENVELOPE:break}}当项目变大的时候,修改一个魔术字符串真的很痛苦。你需要在所有的文件中搜索这个字符串,然后一一修改。如果通过变量使用,虽然需要先导入变量,但需要修改时,只需通过编辑器重命名符号即可轻松完成全局修改。笔者目前正在学习Vue3,其源码中有大量的constXXX=Symbol('xxx')语句。定义私有属性符号可以用来定义真正意义上的私有属性。在下面的示例中,只要Pattern.js不导出符号变量,无论如何都无法从外部访问实例的私有属性。//类定义文件Pattern.jsconstPRIVATE_VALUE=Symbol('privateValue')exportclassPattern{get[PRIVATE_VALUE](){return'Privateproperty,youcannotaccess'}fun(){console.log(this[PRIVATE_VALUE])}}//在其他文件中import{Pattern}from'Pattern.js'constpattern=newPattern()console.log(pattern)//Pattern{}console.log(Object.getOwnPropertySymbols(pattern))//[]console.log(Object.keys(pattern))//[]pattern.fun()//'私有属性,不能访问'扩展遍历ES6新的forof遍历很方便,但是不能直接遍历Object,遍历前需要调用Object.keys方法获取属性列表。我们可以通过Symbol.iterator配合generator来推进对Object.keys的操作,方便我们遍历对象。Object.prototype[Symbol.iterator]=function*(){letkeys=Object.keys(this)for(leti=0;i{throwError('不允许将对象转换为原始数据类型')}console.log(obj=='[objectObject]')//错误:不允许将对象转换为基本数据类型。兼容性除了IE浏览器这个前端大毒瘤外,其他主流浏览器都实现了symbol的所有功能。如果你的项目不需要兼容IE,大胆使用符号,方便你的开发。结论文中如有错误或不准确之处,请务必指正,万分感谢。组织内容并不容易。如果您喜欢或受到启发,希望您能喜欢并关注它,以鼓励作者。