深入了解符号在JavaScript中的使用
什么是符号?
符号不是图标,也不意味着代码中可以使用小图片:
或者其他东西的语法。那么,符号到底是什么?七种数据类型
当JavaScript在1997年标准化时,有六种数据类型。在ES6出现之前,程序中的变量必须是以下六种数据类型之一:
未定义的空布尔数字字符串对象
每种数据类型都是一系列值的组合,前五种数据类型的值的数量是有限的。布尔类型只有两个值:真和假。为布尔类型的变量赋值时,不会生成新值(true和false这两个值是共享的)。对于数字和字符串,它们的值要多得多。标准说法是Number类型(包括NAN)有18,437,736,874,454,810,627个值。很难统计字符串类型的数量。我以为是(2144,115,188,075,855,872?1) 65,535 .但也许我犯了一个错误。
对象值的数量是无限的,每个对象都是唯一的。每次打开网页,都会创建一系列对象。
ES6中的Symbol也是一种数据类型,但它不是字符串或对象,而是一种新的数据类型:第七种数据类型。
我们来看一个场景。也许符号可以派上用场。由布尔值引起的问题
有时,将一些属于其他对象的数据临时存储在另一个对象中非常方便。例如,假设您正在编写一个JS库,并使用CSS中的转换使DOM元素在屏幕上飞行。你已经知道不能同时对同一个div应用多个转场,否则会让动画非常没有吸引力。你确实有办法解决这个问题,但是首先你需要知道div是否已经在移动了。
如何解决这个问题?
方法之一是利用浏览器提供的API检测元素是否处于动画状态,但这是杀鸡儆猴的好方法。当元素设置为移动时,您的库将知道元素正在移动。
你真正需要的是一个机制来跟踪哪些元素在移动。您可以将移动的元素保存在数组中。每次您想要制作元素动画时,首先检查该元素是否已经在此列表中。
啊哈,但是如果你的数组非常大,即使是这种线性搜索也会导致性能问题。
所以,您真正想做的是直接在元素上设置一个标志:
if(element . is moving){ smooth animatics(element);} element.isMoving=trueif(element . is moving){ smooth animatics(element);} element.isMoving=true还有一些潜在的问题,所以我们不得不承认,还有其他代码可能操作这个ODM元素。
在其他代码中,您创建的属性将由for-in或Object.keys()枚举;在其他一些库中,可能使用了相同的方法(在元素上设置了相同的属性),因此这将与您的代码冲突,并产生不可预测的结果;其他库以后可能会用同样的方法,也会和你的代码冲突;标准委员会可能会在每个元素中添加一个. isMoving()本机方法,您的代码将根本无法工作。当然,对于最后三个问题,您可以选择一个没有人会使用的无意义字符串:
if(元素。_ _ $ jorendorff _ animation _ library $ PLEASE _ DO _ NOT _ USE _ THY _ PROPERTY $ is moving _ _){ smooth animations(元素);}元素。_ _ $ jorendorff _ animation _ library $ PLEASE _ DO _ NOT _ USE _ THIS _ PROPERTY $ is moving _ _=true;if(元素。_ _ $ jorendorff _ animation _ library $ PLEASE _ DO _ NOT _ USE _ THY _ PROPERTY $ is moving _ _){ smooth animations(元素);}元素。_ _ $ jorendorff _ animation _ library $ PLEASE _ DO _ NOT _ USE _ THIS _ PROPERTY $ is moving _ _=true;这好像太不靠谱了,让人眼睛都疼。
您还可以使用加密算法来生成几乎唯一的字符串:
//获取1024个Unicode字符的gibilishvar is moving=securerandom . generate name();if(元素[is moving]){ smooth animatics(元素);}元素[Ismoving]=true;//获取1024个Unicode字符的gibilishvar is moving=securerandom . generate name();if(元素[is moving]){ smooth animatics(元素);}元素[Ismoving]=true;object[name]语法允许我们使用任何字符串作为属性名,这样代码就可以正常工作,冲突几乎是不可能的,代码看起来就漂亮多了。
但是,这会导致不好的调试体验。每次使用console.log()打印出包含该属性的元素时,都会看到一个巨大的垃圾字符串。如果有不止一个这样的属性呢?每次刷新后,属性名称都会发生变化。如何让这些属性看起来更直观?
为什么这么难?我们只是想保留一个小标志。使用符号解决问题
符号值可以由程序创建,并且可以用作属性名,而不用担心属性名冲突。
var mySymbol=Symbol();var mySymbol=Symbol();调用Symbol()方法将创建Symbol类型的新值,该值不等于任何其他值。
像数字和字符串一样,符号类型的值也可以用作对象的属性名,正是因为它不等于任何其他值,相应的属性不会冲突:
obj[mySymbol]='好的!';//保证不碰撞console . log(obj[MySymble]);//好的!obj[mySymbol]='好的!';//保证不碰撞console . log(obj[MySymble]);//好的!下面就用Symbol来解决上述问题:
//创建一个唯一的symbolvar is moving=Symbol(' is moving ');if(元素[is moving]){ smooth animatics(元素);}元素[Ismoving]=true;//创建一个唯一的symbolvar is moving=Symbol(' is moving ');if(元素[is moving]){ smooth animatics(元素);}元素[Ismoving]=true;以上代码需要注意几点:
方法Symbol('isMoving ')中的' isMoving '字符串称为Symbol的描述信息,对调试非常有帮助。它可以通过console.log(isMoving)打印,或者当isMoving通过isMoving.toString()转换为字符串时打印,或者显示在一些错误消息中。元素[isMoving]访问符号键属性,该属性与其他属性相同,只是属性名是符号类型的值。与数组一样,符号键属性不能通过。运算符,并且必须用方括号括起来。操作符号键属性也非常方便。通过上面的代码,我们已经知道了如何获取和设置元素[isMoving]的值,也可以这样使用:if (isMoving in element)或者delete element[isMoving]。另一方面,上述代码只能在isMoving的范围内使用,可以实现弱封装机制:在一个模块中创建一些Symbol,只使用模块内部的对象,不用担心与其他模块的代码冲突。因为Symbol最初是为了避免冲突而设计的,所以在遍历JavaScript对象时,不会枚举用Symbol构建的属性。例如,for-in循环将只遍历以字符串为键的属性,Object.keys(obj)和object . getowntpropertynames(obj)也是如此。但是,这并不意味着不能枚举以Symbol为键的属性:可以用object的新方法枚举。getowntpropertysymbols(obj)和Reflect.ownKeys(obj)的新方法可以返回对象中的所有字符串和符号键。(我将在后面的文章中详细介绍新特性Reflect。)
库和框架的设计者会发现Symbol的许多用途。后面我们会看到,JavaScript本身也是被广泛使用的。符号到底是什么
符号的类型()“符号”符号的类型()“符号”符号是完全不同的东西。一旦创建,您就不能更改它们,也不能在它们上设置属性(如果您试图在严格模式下这样做,您将得到一个TypeError)。它们可以用作属性名,与字符串的属性名没有区别。
另一方面,每个符号都是唯一的,不会复制其他符号(即使它是用相同的符号描述创建的)。创建符号和创建对象一样方便。
ES6中的符号类似于传统语言(如Lisp和Ruby)中的符号,但并没有完全复制到JavaScript中。在Lisp中,所有的标识符都是符号;在JavaScript中,标识符和大多数属性仍然是字符串,符号只是提供了一个额外的选择。
值得注意的是,与其他类型不同,Symbol不能自动转换为字符串。当试图将符号强制转换为字符串时,将返回类型错误。
var sym=Symbol(' 3 ');您的符号是“sym//TypeError:无法将符号转换为字符串`您的符号是${sym}`//TypeError:无法将符号转换为字符串var sym=Symbol(' 3 ');您的符号是“sym//TypeError :无法将符号转换为字符串`您的符号是$ {sym} `//TypeError :无法将符号转换为字符串应避免这种强制转换,并应使用String(sym)或sym.toString()进行转换。获取符号的三种方法
Symbol()每次调用时都会返回一个唯一的Symbol。符号. for(字符串)从符号注册表中返回相应的符号。与前面的方法不同,符号注册表中的符号是共享的。也就是说,如果您三次调用Symbol.for('cat '),将返回相同的Symbol。当不同页面或同一页面上的不同模块需要共享Symbol时,注册表非常有用。Symbol.iterator返回一些由语言预定义的符号,每个符号都有其特殊的用途。如果你还不确定Symbol是否有用,那么接下来的内容会很有意思,因为我会为你演示Symbol的实际应用。符号在ES6规范中的应用
我们已经知道符号可以用来避免代码冲突。在介绍迭代器时,我们还分析了for(my array的var项)是从调用myArray[Symbol.iterator]()开始的。当时我提到可以用myArray.iterator()代替这个方法,但是向后兼容Symbol更好。
ES6中有一些地方使用了Symbol。(这些功能还没有在FireFox中实现。)
使实例可扩展。在ES6中,构造函数的对象实例的表达式被标准化为构造函数的一种方法:构造函数[符号。hasinstance](对象),这意味着它是可扩展的。消除新功能和旧代码之间的冲突。支持新类型的字符串匹配。在ES5中,当str.match(myObject)被调用时,第一次尝试是将myObject转换为RegExp对象。在ES6中,首先我们会检查是否有myObject[符号。方法,并在正则表达式工作的所有地方提供自定义字符串解析方法。这些用途仍然相对狭窄,但是仅通过我的文章中的代码很难看到这些新特性的显著影响。JavaScript的Symbol是PHP和Python中_ _下划线的改进版本,标准组织将使用该版本在不影响现有代码的情况下为语言添加新功能。
版权声明:深入了解符号在JavaScript中的使用是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。