复习再深入 之 Javascript中的转义和编码

前一阵做活动有一个分享文案总是分享错误,排除法之后发现是一个字符的编解码问题。好几次遇到这种问题都是懵过去的,这次有时间写篇文章大概梳理一下。

字符集?字符编码?

首先我们知道,计算机能接收的指令和能处理的信息都最后都是要转化成二进制的数据的。而在很早以前,我们需要处理的是文本,这就衍生了 ASCII 字符集,规定了打印字符(例如大写小写英文字母、数字,和一些其他字符),控制字符(例如回车,上下左右)和编号的对应关系,这个编号就是像 URI 一样给字符的唯一标识。而字符编码则是根据这个编号,对应写入字节流。

为了方便大家理解,放出一个 ASCII 表再熟悉一下:

ASCII 表

我们后面说到的的原理都大同小异,就是把一个独一无二的编号和一个字符对应起来,而字符编码的过程就是让计算机拿到这个编号之后知道这个东西应该展示/存储成什么样子。

ASCII编解码示意图

但是我们刚才说到的字符集是基于单字节编码,什么叫单字节编码?看到上图的左上角低四位/高四位没?一共8位即一个字节就可以表示一个字符,这就是单字节编码。掐指一算8位表示一个字符,这一共也才能表示256个字符啊,太少了!发现 ASCII 字符集远远不够用,多用几位表示不就行了?所以有了多字节编码方式。例如中国使用的就是双字节字符编码(使用最多两个字节来编码),并且我们有自己的字符集 GB2312,GBK 是在前者的基础上增加了繁体字等的编码。

到此为止,我们的字符集都不能包含人类所用的全部字符。然后就衍生了 Unicode 字符集。它为每个字符统一编号,分配唯一的字符码。

上面字符集和编码方式是直接绑定在一起的,想扩展是很复杂的事情;而 unicode 是要涵盖所有字符,包括未来不可预知的字符。为了提高可扩展性,我们把字符集和字符编码分开,虽然 编号(unicode 码)相同,但是最终决定字节流的是你的字符编码方案。举几个我们相当熟悉的字符编码,UTF-8和 UTF-16,见图。

unicode 编解码图示

所以说到这里其实我们也知道了,unicode 编码和 unicode 字符集不是一回事。 unicode 编码是能对 unicode 字符码转换成字节流的字节编码方式的统称,包含 urf-8等实现方式。

关于乱码?

我不知道你在说什么,就没法解析你的话。我用codepage936的字符编码去解你用 utf-8编码出的字节流,自然不知道你在说什么。

网页指定字符编码的位置一般就是,后端返回的响应头的 content-type;网页 meta:http-equiv;

在 Javascript 中的应用?

我能想到的就一下这些方法,大家可以补充。

encodeURI:是按 utf-8 进行编码,除了:; , / ? : @ $ = + & (前面这些是保留字符,保留的原因不再赘述) 字母 数字 _ - · ! ~ * ' ( ) #

encodeURIComponent:也是按 utf-8 进行编码,除了:字母 数字 _ - · ! ~ * ' ( ) #

btoa:将 ASCII 字符串或者二进制数据转为 base64编码过的字符串,该方法不能直接作用于 Unicode 字符串

atob:反过来

JSON.parse: 经历两次转义。第一次调用 toString()方法(注意在这个方法中已经对内部的\n 等进行一次转义),第二次把JSON字符串转义为 JSON 对象。

eval:同上,并且和 parse 一样可以把符合 json 标准的字符串转化为 json 对象,但是因为设计安全问题所以不推荐使用

有时候直接 console 是对的,但是放在 html 不对,是因为 console 其实是自带一次 toString()的过程的,而 toString()会转义。

反斜线到底什么用?首先是展示一些不能展示的ASCII字符,例如回车\n,tab键\t 等。其次是展示一些特殊用途的字符,双引号\" 等等。本质上他的作用是替代一些不能表示的东西。

有时候反斜线展示在页面上,不能成功显示为应该显示的字符,是因为没有经历解码的过程。

为什么在 控制台的HTML 里直接改成\n 不能用,因为直接在控制台里写是不经过转义的。。

为啥innertext="\n"显示结果是回车,innerHTML="\n"显示结果不是回车(也不直接展示\n,因为这两个方法都会先转义)?因为前者是把你给他的东西做基础转义之后原封不动的放进去,而后者会经过一次 HTML 转义,你在代码里直接写回车也不会搭理你的。。。(是 HTML 文本中空白符的默认处理方式,可以修改,比如你 css 中的 white-space

下面贴一段转义的定义(来自百度百科):

转义字符串(Escape Sequence)也称字符实体(Character Entity)。在HTML中,定义转义字符串的原因有两个:第一个原因是像“<”和“>”这类符号已经用来表示HTML标签,因此就不能直接当做文本中的符号来使用。为了在HTML文档中使用这些符号,就需要定义它的转义字符串。当解释程序遇到这类字符串时就把它解释为真实的字符。在输入转义字符串时,要严格遵守字母大小写的规则。第二个原因是,有些字符在ASCII字符集中没有定义,因此需要使用转义字符串来表示。

其实所有编程语言,拥有转义字符的原因基本上是两点:一、使用转义字符来表示字符集中定义的字符,比如ASCll里面的控制字符及回车换行等字符,这些字符都没有现成的文字代号。所以只能用转义字符来表示 。二、某一些特定的字符在编辑语言中被定义为特殊用途的字符。这些字符由于被定义为特殊用途,它们失去了原有的意义。比如说HTML中,<被HTML定义为标签的开始,所以当我们转入<时,HTML就会把它当作为开始,而不是当作一个<来看待。再如PHP 的双引号("),被PHP定义为字符串的外围标签,所以如果你在一对双引号里面,还想要使用双引号,只能使用转义字符了。不然PHP就会报错了。

从上面也可以看出转义无非是两种情况:1:将普通字符转为特殊用途,一般是编程语言中,用于表示不能直接显示的字符,比如后退键,回车键,等。2:用来将特殊意义的字符转换回它原来的意义。一般用在正则表达式中。还有有些脚本语言是弱类型,有些语言比如HTML 并不是编程语言,而是标记语言,有些语言只有一种类型 比如shell 脚本语言,这些语言中字符串都不加引号” ” ,或者可以不加引号“ ”,所以有时候需要转义字符说明某字符此时的身份是普通字符,而不是有特殊意义的元字符。

base64?用武之地?编码过程?

是一种基于64个可打印字符来表示二进制数据的方法,是用于传输8bit 字节码的编码方式之一。

是从二进制到文本数据的过程。

具有不可读性,需要解码后才能阅读。

因为 base64可以表示所有二进制数据,所以基本上意味着所有数据都可以转换成 base64的格式。

拿我们最熟悉的 ASCII 举例子,我们知道在 ASCII 码中,128~255是不可见字符。而这些字符在传输过程中,如果直接传输会在中间过程被处理错误,且这个过程是不可逆的(原有的字符会被替换丢失),所以我们要保证传输过程中没有不可见字符,让数据符合传输协议的要求。相当于 base64就像我们为了数据传输准确而带的通行证。

但是注意 base64编码过后的数据大概会编程原来的4/3,因为有填补空位的过程。

我们常用的场景就是,图片传输,根证书,邮件附件等。

编码过程:对于非二进制数据,是先将其转换成二进制形式,然后每连续6比特(2的6次方=64)计算其十进制值,根据该值在上面的索引表中找到对应的字符,最终得到一个文本字符串。

%是啥意思?为啥 encode 完了都带上这个,但是明明字符编码完不是这样的?

而且为啥我在 HTML 里直接写\n 不行?

在 c 语言中,转义用\表示,在 URI 协议中,转义字符是百分号%。并且其他语言的转义字符可能各不相同。

这也就解答了为什么你直接在HTML 里用\n是不行的,因为HTML 中转义字符不是\,他只当这是两个正常的字符,一个反斜线一个字母 n。只是在 Javasciprt 这门语言里(当然还有很多其他语言例如 C)会转义成回车。

参考文章:

前端中关于编码和转码的知识小总结

关于字符编码,你所需要知道的

小心字符串中的转义字符

https://segmentfault.com/q/1010000009768523/a-1020000009774588

https://stackoverflow.com/questions/12694110/rendering-newlines-in-escaped-html

转义字符

为什么要使用base64编码,有哪些情景需求?

base64编码原理与应用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容