假设咱们已经知道Unicode字符集,若是不清楚也可阅读本文,而后等待下一篇主要介绍Unicode的文章。html
今天咱们主要来聊聊这些行走在阳光下的不可见字符。不可见字符在计算机科学和通讯学中被称为控制字符或非打印字符,是字符集中的一个码位(code point),不是一个书面符号,也就是在通常的书面呈现环境中它是不可见字符。前端
在前端的世界里,咱们翻看MDN的文档就能看到相关信息,好比String的 转义字符(Escape Notation)模块就有介绍,git
咱们能够尝试,在这些转义字符中,如 '\f', '\b'等咱们去新建一个这样的字符串变量而后console出来是看不见的,可是咱们去看该字符串的长度却不等于0。github
咱们能够在ECMAScript标准中找到相关介绍web
A string literal is zero or more characters enclosed in single or double quotes. Each character may be represented by an escape sequence. All characters may appear literally in a string literal except for the closing quote character, backslash, carriage return, line separator, paragraph separator, and line feed. Any character may appear in the form of an escape sequence.ajax
就是除了"closing quote character, backslash, carriage return, line separator, paragraph separator, and line feed" 都能在字符串中逐字的出现。markdown
总的来讲不可见字符最大的做用就是不可见性,那么咱们能够利用这个生成一些带有不可见字符的信息展现在某些地方。那么,怎么去生成这一整套工具呢?让咱们来作一下任务拆解,app
根据以上任务步骤,就能进行功能开发了,工具
1 const zeroWidthSpace = '\u200B' 2 const zeroWidthJoiner = '\u200D' 3 const zeroWidthNonJoiner = '\u200C' 4 const zeroWidthNonBreakSpace = '\uFEFF' 5 6 function createEncryptionText(text) { 7 if (!text || typeof text !== 'string') { 8 throw new Error('invalid param, param must be string') 9 } 10 11 const binaryText = textToBinary(text) 12 return binaryText 13 .split('') 14 .map(b => { 15 const num = parseInt(b, 10) 16 if (num === 1) { 17 return zeroWidthSpace 18 } 19 20 if (num === 0) { 21 return zeroWidthNonJoiner 22 } 23 24 return zeroWidthJoiner 25 }) 26 .join(zeroWidthNonBreakSpace) 27 } 28 29 function charToBinary(char) { 30 return char.charCodeAt(0).toString(2) 31 } 32 33 function textToBinary(text) { 34 return text 35 .split('') 36 .map(item => padStar(charToBinary(item))) 37 .join(' ') 38 } 39 40 function padStar(text, length = 8, chars = '0') { 41 if (typeof text !== 'string') { 42 throw new Error('invalid params. text must be string') 43 } 44 45 return ( 46 Array(length) 47 .fill(chars) 48 .slice(text.length) + text 49 ) 50 } 51 52 console.log(createEncryptionText('wfsovereign')) // "" 53 console.log(createEncryptionText('wfsovereign').length) // 195
这里首先准备了一些隐形的Unicode字符用于对要加密文本(后面称之为签名)的替换,而后定义好替换的规则,将签名先转换成二进制而后逐位进行替换。上面咱们能够看到加密后的文本输出好似一个空字符串,然而咱们看到该字符串的长度倒是195,由此证实咱们成功的将签名转化为了隐形文本。网站
对于二、3点这里咱们就不展开详说了,我将整个加解密以及隐形码位的提取抽成了一个ZeroWidthCharacterEncryptionManager 类,而后将代码放到了个人GitHub,感兴趣的同窗能够移步查阅。其中须要的注意的两点这里我提一下,一个是反隐形加密的时候要按照加密的规则一一对应,这样才能获得原始签名;另外一个是提取一段文本内容的时候,我采用的是正则,这个正则如何写是根据咱们采起的一些隐形的码位来定的,好比上面我选择的zeroWIdthSpace等,对应的正则就应该是*/[\u200B-\u200C\uFEFF]+/* 。
根据上面的工具类,咱们看到的一个应用场景就是在一段文本中加上隐形签名或者水印,这样咱们生成的文本内容若是被他人传播的话,就能经过隐形签名来检测是不是从咱们这里传播出去的,感受还能保护版权啥的,和在一些网站copy内容会自动带上出处的作法有殊途同归之妙啊~
那么,此外还有没有其余做用?这就要看聪明的你的奇思妙想咯 :)
ps: 及时总结,静心沉淀;如风少年,砥砺前行。
如想了解更多,请移步个人博客
欢迎关注个人公众号 “和F君一块儿xx”
参考资料: