對於一個輸入框, 若是其id中含有冒號(:),選擇器使用須要有特殊寫法, javascript
例如 id爲下css
<input type="text" value="ddd" id="a:b">html
使用$(selector)直接使用#id值, 找不到DOMjava
console.log("#a:b")
console.log($("#a:b").length) // output 0jquery
通過探索可使用如下兩個方法選擇到DOM:css3
$("#a\\:b");瀏覽器
$("[id^='a:b']");app
其中第一種, 須要在冒號(:)前添加一個反斜槓(\), 某些同窗要問了,命名是兩個反斜槓, 忽悠我?學習
請看下節介紹。spa
js中的字符串語法須要佔用一些元字符, 對於這些元字符若是須要想要在字符串中出現就須要使用轉移:
轉義表: FROM http://www.w3school.com.cn/js/js_special_characters.asp
代碼 | 輸出 |
---|---|
\' | 單引號 |
\" | 雙引號 |
\& | 和號 |
\\ | 反斜槓 |
\n | 換行符 |
\r | 回車符 |
\t | 製表符 |
\b | 退格符 |
\f | 換頁符 |
事實上,從上表中看以看出,不只僅是元字符須要顯示才轉義(" -> \"), 還有使用轉移後能夠將特定字符轉義爲另外含義的狀況, 例如 n -> \n 變爲換行符。
從學習上能夠按照以下邏輯總體理解js轉義:
一、 js字符串使用 單引號 或者 雙引號 做爲字符串的」括號」, 表示一個總體字符串, 引號內部爲字符串內容,
二、 那麼問題來了, 字符串內容中要想包括 引號, 怎麼辦?
三、 js設計者(Brendan Eich)考慮, 相似c語言中轉義方法, 使用\x 方式來表示x, 即轉義規則 \x == x, 這裏x包括引號(‘ 「)。
四、 既然使用了\x格式執行轉義, 那字符串內容中要想包含\怎麼辦? 若是直接使用\, 則極可能跟其後面一個正常字符意外的轉義。
五、 既然轉義規則已定 \x == x, 那麼\在字符串內容中存在的場景,正符合此規則, 規則應用效果爲 \\ == \ 、
六、 最後還有一種場景, 存在不少控制字符(包括格式控制字符,例如\n、 和不可打印字符), 這些字符自己沒有可打印字符的表現形式,即沒有在ascii中[32, 126]出現。
可是字符只能書寫[32, 126]之間的字符, 因此這種狀況下須要定義一種新的轉義, 爲不增長轉義元字符, 轉義字符還爲\,
轉義規則爲 \x == y, x in [32, 126], y in [0, 31] or 127
說明: 若是對[32, 126]之間的非3 和 6中使用字符進行轉義,即應用規則(\x), 則獲得仍是x, 符合轉義規則。
總結以下圖:
demo代碼:
console.log('---- \\x present x (x is printable character) ----'); console.log('slash + slash='+"\\"); // \ is part of transfer encoding syntax console.log('slash + "='+"\""); // " is collision with string syntax double quotation, eg "xx" wrapped by " console.log('---- \\x present control character ----'); console.log('slash + n='+"\n"); // \n present line break console.log('---- \\x equal x when x is not needed transfer concoding ----'); console.log('slash + 8='+"\8"); // \8 == 8 console.log('slash + o='+"\o"); // \o == o console.log('slash + :='+"\:"); // \: == :
通過分析JQuery源代碼, $("")的調用次序
一、 $ === jQuery.fn.init
二、 走到 jQuery.fn.init 中 return ( context || rootjQuery ).find( selector );
三、 find == jQuery.find == Sizzle
四、Sizzle 調用 newContext.querySelectorAll( newSelector )
而 querySelectorAll 爲 最新瀏覽器都實現的 選擇器查詢接口,
各個DOM上都實現了 此接口, 詳情見 http://www.cnblogs.com/snandy/archive/2011/03/30/1999388.html
因此查看到這裏, 說明jquery 和 sizzle 未對選擇器作處理。徹底是 瀏覽器實現 的 querySelectorAll接口行爲。
W3C對選擇器有一套規範:
http://www.w3.org/TR/css3-selectors/#selectors
其中有對 id選擇器的說明, 可見選擇器的中 : 爲選擇器的元字符, 即保留字符, 作僞類使用,其餘狀況不能與之衝突。
因此讀到此處,看官明白 $("#a\\:b"); 爲何要對冒號添加轉義了吧!
對於此選擇器 即 "#a\\:b" 因爲其自己是js字符串, \\表示\, 那麼這個字符串在內存中的存儲爲
能夠猜想 querySelectorAll 的實現, 首先會同js對selector字符串 作解析, 首先分析 : 前面不帶\ 的冒號, 將其先後內容拆分, 前面爲 選擇器主體部分, 後面爲僞類部分,
而後對 前面主題部分, 執行js字符串轉義解析, 相似eval接口執行行爲 :
eval("var evalselector = '#a\\:b';")
console.log(evalselector); // output #a:b
將 轉義表寫 還原爲
運行以下js:
console.log("#a:b") console.log("#a\:b") console.log(document.querySelectorAll("#a\\:b").length) console.log("[id^='a:b']") console.log(document.querySelectorAll("[id^='a:b']").length)
打印以下:
結論 :
一、冒號(:)屬於js中不用轉義的普通可見字符, "#a:b" === "#a\:b"
二、 "#a\\:b" 爲避免css selector僞類標識符號衝突的解法, 通過 js字符串轉義,須要兩個反斜槓\, 最後在 querySelectorAll接口中,將\:轉換爲:
三、 對於id中含有冒號的狀況, 可使用"[id^='a:b']"的表寫方式, 這種不須要對冒號轉義, 由於這種格式不存在衝突的可能。
建議 id可變的狀況,都使用"[id^='a:b']"方式。
<html> <head> <script type="text/javascript" src="./jquery.js"></script> <style> </style> </head> <body> <input type="text" value="ddd" id="a:b"> <script> console.log('---- \\x present x (x is printable character) ----'); console.log('slash + slash='+"\\"); // \ is part of transfer encoding syntax console.log('slash + "='+"\""); // " is collision with string syntax double quotation, eg "xx" wrapped by " console.log('---- \\x present control character ----'); console.log('slash + n='+"\n"); // \n present line break console.log('---- \\x equal x when x is not needed transfer concoding ----'); console.log('slash + 8='+"\8"); // \8 == 8 console.log('slash + o='+"\o"); // \o == o console.log('slash + :='+"\:"); // \: == : console.log('#a+slash+slash+:b='+"#a\\:b"); // #a\\:b == #a\:b console.log('jquery length='+$("#a\\:b").length); // length == 1 with selector #a\\:b console.log('jquery length='+$("[id^='a:b']").length); // length == 1 with selector [id^='a:b'] console.log("#a:b") //output #a:b console.log("#a\:b") //output #a:b console.log(document.querySelectorAll("#a\\:b").length)//output 1 console.log("[id^='a:b']") //: do not need transfer coding console.log(document.querySelectorAll("[id^='a:b']").length) //output 1 </script> </body> </html>