JS字串編碼

LIJING0906發表於2018-10-26

此文首發於 lijing0906.github.io

最近在工作中遇到一個bug:

背景

新增或者編輯標籤時,輸入框失焦時需要校驗標籤名是否與已有標籤名重複,而標籤名只有字數限制(1-10個字元)。

問題

校驗的介面是get請求,當標籤名以“#”、“&”結尾時,會出現一點小問題:比如已存在名為“aa”的標籤,當輸入“aa#”或“aa&”(這兩個標籤名不存在)失焦校驗時,後臺返回“該標籤名已存在”,不應該啊,明明沒有這個標籤名呀???

找bug

  1. 首先想到的是列印一下輸入框的值和傳給後臺的標籤名,列印結果跟我輸入的一樣,嗯,那不是這裡出問題
  2. 然後F12開啟開發者工具,發現失焦呼叫介面時,傳的引數不是我填入的值,問題就出現在這兒了:以“#”結尾傳的參是“aa”:
    JS字串編碼
    以“&”結尾傳的參是“aa”,還莫名多了一個空欄位的引數,值也為空:
    JS字串編碼

Tell me why?

想必這應該是http協議的問題,網上查閱了一番,參考原文講解了URL的組成,舉例一個URL:

http: // www.shibazi.com:8080 / news / index.asp ? boardID=5&ID=24618&page=1#name

從上面的URL可以看出,一個完整的URL包括以下幾部分: 1、協議部分:該URL的協議部分為“http:”,這代表網頁使用的是HTTP協議。在Internet中可以使用多種協議,如HTTP,FTP等等本例中使用的是HTTP協議。在"HTTP"後面的“//”為分隔符

2、域名部分:該URL的域名部分為“www.shibazi.com”。一個URL中,也可以使用IP地址作為域名使用

3、埠部分:跟在域名後面的是埠,域名和埠之間使用“:”作為分隔符。埠不是一個URL必須的部分,如果省略埠部分,將採用預設埠80

4、虛擬目錄部分:從域名後的第一個“/”開始到最後一個“/”為止,是虛擬目錄部分。虛擬目錄也不是一個URL必須的部分。本例中的虛擬目錄是“/news/”

5、檔名部分:從域名後的最後一個“/”開始到“?”為止,是檔名部分,如果沒有“?”,則是從域名後的最後一個“/”開始到“#”為止,是檔案部分,如果沒有“?”和“#”,那麼從域名後的最後一個“/”開始到結束,都是檔名部分。本例中的檔名是“index.asp”。檔名部分也不是一個URL必須的部分,如果省略該部分,則使用預設的檔名

6、錨部分:從“#”開始到最後,都是錨部分。本例中的錨部分是“name”。錨部分也不是一個URL必須的部分

7、引數部分:從“?”開始到“#”為止之間的部分為引數部分,又稱搜尋部分、查詢部分。本例中的引數部分為“boardID=5&ID=24618&page=1”。引數可以允許有多個引數,引數與引數之間用“&”作為分隔符。

著重看第6、7條就能明白為什麼以“#”和“&”結尾會出問題。“#”後面是錨,http自動去掉了“#”;“&”是引數分隔符,自然就多出了一個空欄位,值也為空。

修復bug

  1. 參考原文 escape(URIstring) 該方法不會對ASCII字母和數字進行編碼,也不會對下面這些 ASCII 標點符號進行編碼: * @ - _ + . / ,其他所有的字元都會被轉義序列替換。返回值是已編碼的string的副本,其中某些字元被替換成了十六進位制的轉義序列。

那就用這個吧,但是後臺對於人民幣符號“¥”並不能解碼,那就試試其他的吧。

  1. 參考原文 encodeURI(URIstring) 該方法不會對ASCII字母和數字進行編碼,也不會對這些 ASCII 標點符號進行編碼: - _ . ! ~ * ' ( ) 。該方法的目的是對 URI 進行完整的編碼,因此對以下在URI中具有特殊含義的ASCII標點符號,encodeURI()函式是不會進行轉義的:;/?:@&=+$,#

這個方法更不能用啦

  1. 參考原文 encodeURIComponent(URIstring) 該方法不會對ASCII字母和數字進行編碼,也不會對這些ASCII標點符號進行編碼: - _ . ! ~ * ' ( ) 。其他字元(比如 :;/?:@&=+$,# 這些用於分隔URI元件的標點符號),都是由一個或多個十六進位制的轉義序列替換的。

誒,這個正是我需要的,試試這個,結果讓人很滿意,中英文的所有標點符號特殊字元都能進行編碼。

相關文章