復習再深入 之 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閱讀 230,002評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,400評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,136評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,714評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,452評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,818評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,812評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,997評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,552評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,292評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,510評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,721評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,121評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,429評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,235評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,480評論 2 379

推薦閱讀更多精彩內容