整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          JavaScript中的String類型

          JavaScript中的String類型

          tring類型

          JavaScript中的String類型

          String 類型是字符串的對象包裝類型,可以像下面這樣使用 String 構造函數來創建。

          String 對象的方法也可以在所有基本的字符串值中訪問到。其中,繼承的 valueOf()、toLocale- String()和 toString()方法,都返回對象所表示的基本字符串值。

          String 類型的每個實例都有一個 length 屬性,表示字符串中包含多個字符。

          var stringValue="hello world";
          alert(stringValue.length); //"11"
          

          這個例子輸出了字符串"hello world"中的字符數量,即"11"。應該注意的是,即使字符串中包 含雙字節字符(不是占一個字節的 ASCII 字符),每個字符也仍然算一個字符。

          String 類型提供了很多方法,用于輔助完成對 ECMAScript 中字符串的解析和操作。

          1.字符方法

          兩個用于訪問字符串中特定字符的方法是:charAt()和 charCodeAt()。這兩個方法都接收一個 參數,即基于 0 的字符位置。其中,charAt()方法以單字符字符串的形式返回給定位置的那個字符 (ECMAScript 中沒有字符類型)。

          var stringValue="hello world";
          alert(stringValue.charAt(1)); //"e"
          

          字符串"hello world"位置 1 處的字符是"e",因此調用 charAt(1)就返回了"e"。如果你想得到 的不是字符而是字符編碼,那么就要像下面這樣使用 charCodeAt()了。

          var stringValue="hello world";
          alert(stringValue.charCodeAt(1)); //輸出"101" 
          

          這個例子輸出的是"101",也就是小寫字母"e"的字符編碼。

          ECMAScript 5 還定義了另一個訪問個別字符的方法。在支持此方法的瀏覽器中,可以使用方括號加數 字索引來訪問字符串中的特定字符,

          var stringValue="hello world";
          alert(stringValue[1]); //"e"
          

          使用方括號表示法訪問個別字符的語法得到了 IE8 及 Firefox、Safari、Chrome 和 Opera 所有版本的 支持。如果是在 IE7 及更早版本中使用這種語法,會返回 undefined 值(盡管根本不是特殊的 6 undefined 值)。

          2.字符串操作方法

          第一個就是 concat(),用于將一或多個字符串拼接起來,返回拼接得到的新字符串。

          var stringValue="hello ";
          var result=stringValue.concat("world"); alert(result); //"hello world" alert(stringValue); //"hello" 
          

          在這個例子中,通過 stringValue 調用 concat()方法返回的結果是"hello world"——但 stringValue 的值則保持不變。實際上,concat()方法可以接受任意多個參數,也就是說可以通過它 9 拼接任意多個字符串。

          var stringValue="hello ";
          var result=stringValue.concat("world", "!");
          alert(result); //"hello world!" alert(stringValue); //"hello" 
          

          這個例子將"world"和"!"拼接到了"hello"的末尾。雖然 concat()是專門用來拼接字符串的方 11 法,但實踐中使用更多的還是加號操作符(+)。而且,使用加號操作符在大多數情況下都比使用 concat() 方法要簡便易行(特別是在拼接多個字符串的情況下)。

          ECMAScript 還提供了三個基于子字符串創建新字符串的方法:slice()、substr()和 substring()。 12 這三個方法都會返回被操作字符串的一個子字符串,而且也都接受一或兩個參數。第一個參數指定子字 符串的開始位置,第二個參數(在指定的情況下)表示子字符串到哪里結束。具體來說,slice()和 substring()的第二個參數指定的是子字符串最后一個字符后面的位置。而 substr()的第二個參數指定的則是返回的字符個數。如果沒有給這些方法傳遞第二個參數,則將字符串的長度作為結束位置。與 concat()方法一樣,slice()、substr()和 substring()也不會修改字符串本身的值——它們只是 返回一個基本類型的字符串值,對原始字符串沒有任何影響。

          var stringValue="hello world";
          alert(stringValue.slice(3));
          alert(stringValue.substring(3));
          alert(stringValue.substr(3));
          alert(stringValue.slice(3, 7));
          alert(stringValue.substring(3,7));
          alert(stringValue.substr(3, 7));
          //"lo world"
          //"lo world"
          //"lo world"
          //"lo w"
          //"lo w"
          //"lo worl"
          

          這個例子比較了以相同方式調用 slice()、substr()和 substring()得到的結果,而且多數情 況下的結果是相同的。在只指定一個參數 3 的情況下,這三個方法都返回"lo world",因為"hello" 中的第二個"l"處于位置 3。而在指定兩個參數 3 和 7 的情況下,slice()和 substring()返回"lo w" ("world"中的"o"處于位置 7,因此結果中不包含"o"),但 substr()返回"lo worl",因為它的第二 個參數指定的是要返回的字符個數。

          在傳遞給這些方法的參數是負值的情況下,它們的行為就不盡相同了。其中,slice()方法會將傳 入的負值與字符串的長度相加,substr()方法將負的第一個參數加上字符串的長度,而將負的第二個 參數轉換為 0。最后,substring()方法會把所有負值參數都轉換為 0。

          var stringValue="hello world";
          alert(stringValue.slice(-3));
          alert(stringValue.substring(-3));
          alert(stringValue.substr(-3));
          alert(stringValue.slice(3, -4));
          alert(stringValue.substring(3, -4));
          alert(stringValue.substr(3, -4));
          //"rld" //"hello world" //"rld"
          //"lo w" //"hel" //""(空字符串) 
          

          這個例子清晰地展示了上述三個方法之間的不同行為。在給 slice()和 substr()傳遞一個負值 參數時,它們的行為相同。這是因為-3 會被轉換為 8(字符串長度加參數 11+(?3)=8),實際上相當 于調用了 slice(8)和 substr(8)。但 substring()方法則返回了全部字符串,因為它將-3 轉換 成了 0。

          當第二個參數是負值時,這三個方法的行為各不相同。slice()方法會把第二個參數轉換為 7,這 就相當于調用了 slice(3,7),因此返回"lo w"。substring()方法會把第二個參數轉換為 0,使調 用變成了 substring(3,0),而由于這個方法會將較小的數作為開始位置,將較大的數作為結束位置, 因此最終相當于調用了 substring(0,3)。substr()也會將第二個參數轉換為 0,這也就意味著返回 包含零個字符的字符串,也就是一個空字符串。

          3.字符串位置方法

          有兩個可以從字符串中查找子字符串的方法:indexOf()和 lastIndexOf()。這兩個方法都是從 一個字符串中搜索給定的子字符串,然后返子字符串的位置(如果沒有找到該子字符串,則返回-1)。 這兩個方法的區別在于:indexOf()方法從字符串的開頭向后搜索子字符串,而 lastIndexOf()方法 是從字符串的末尾向前搜索子字符串。

          var stringValue="hello world";
          alert(stringValue.indexOf("o")); //4
          alert(stringValue.lastIndexOf("o")); //7
          

          子字符串"o"第一次出現的位置是 4,即"hello"中的"o";最后一次出現的位置是 7,即"world"中的 "o"。如果"o"在這個字符串中僅出現了一次,那么 indexOf()和 lastIndexOf()會返回相同的位置值。

          這兩個方法都可以接收可選的第二個參數,表示從字符串中的哪個位置開始搜索。換句話說, indexOf()會從該參數指定的位置向后搜索,忽略該位置之前的所有字符;而 lastIndexOf()則會從 指定的位置向前搜索,忽略該位置之后的所有字符。

          var stringValue="hello world";
          alert(stringValue.indexOf("o", 6)); //7
          alert(stringValue.lastIndexOf("o", 6)); //4
          

          在將第二個參數 6 傳遞給這兩個方法之后,得到了與前面例子相反的結果。這一次,由于 indexOf()是從位置 6(字母"w")開始向后搜索,結果在位置 7 找到了"o",因此它返回 7。而 last- IndexOf()是從位置 6 開始向前搜索。結果找到了"hello"中的"o",因此它返回 4。在使用第二個 參數的情況下,可以通過循環調用 indexOf()或 lastIndexOf()來找到所有匹配的子字符串,如下 面的例子所示:

          var stringValue="Lorem ipsum dolor sit amet, consectetur adipisicing elit"; var positions=new Array();
          var pos=stringValue.indexOf("e");
          while(pos > -1){
           positions.push(pos);
           pos=stringValue.indexOf("e", pos + 1);
          }
          alert(positions); //"3,24,32,35,52"
          

          這個例子通過不斷增加 indexOf()方法開始查找的位置,遍歷了一個長字符串。在循環之外,首 先找到了"e"在字符串中的初始位置;而進入循環后,則每次都給 indexOf()傳遞上一次的位置加 1。 這樣,就確保了每次新搜索都從上一次找到的子字符串的后面開始。每次搜索返回的位置依次被保存在 數組 positions 中,以便將來使用。

          、string類型

          string類型用于表示由零或多個16位Unicode字符組成的字符序列,即字符串。字符串可以由雙引號或單引號表示,下面兩種字符串的寫法都是有效的:

          var firstName="Nicholas";
          var lastName='zakas';
          

          與PHP中的雙引號和單引號會影響對字符串的解釋方式不同,ECMAScript中的這兩種語法形式沒有什么區別。用雙引號表示的字符串和單引號表示的字符串完全相同。不過,以雙引號開頭的字符串也必須以雙引號結尾,而以單引號開頭的字符串必須以單引號結尾。

          二、字符字面量

          string數據類型包含一些特殊的字符字面量,也叫轉義字符,用于表示非打印字符,或者具有其他用途的字符。這些字符字面量如下表所示:

          這些字符字面量可以出現在字符串的任意位置,而且會被當作一個字符來解析,來看下面的例子:

          var text="This is the letter sigma: \u03a3";
          alert(text.length); //輸出28
          

          這個例子中的變量text有28個字符,其中6個字符長的轉義序列表示1個字符。任何字符串的長度都可以通過訪問其length屬性取得。

          三、轉換為字符串

          要不一個值轉換為一個字符串有三種方式。

          1、toString()方法

          第一種是使用幾乎每個值都有的toString()方法,這個方法唯一要做的就是返回相應值的字符串表現。數值、布爾值、對象和字符串值都有toString()方法,但null和undefined值沒有這個方法。

          var age=11;
          var ageAsString=age.toString(); //字符串"11"
          var found=true;
          var foundAsString=found.toString(); //字符串"true"
          

          多數情況下,調用toString()方法不必傳遞參數。但是,在調用數值的toString()方法時,可以傳遞一個參數:輸出數值的基數。默認情況下,toString()方法以十進制格式返回數值的字符串表示。而通過傳遞基數,toString()可以輸出以二進制、八進制、十六進制。如下所示:

          var num=10;
          alert(num.toString()); //"10"
          alert(num.toString(2)); //"1010"
          alert(num.toString(8)); //"12"
          alert(num.toString(10)); //"10"
          alert(num.toString(16)); //"a"
          

          2、String()方法

          在不知道要轉換的值是不是null或undefined的情況下,還可以使用轉型函數String(),這個函數能夠將任何類型的值轉換為字符串。String()函數遵循下列轉換規則:

          • 如果值有toString()方法,則調用該方法(沒有參數)并返回相應的結果。
          • 如果值是null,則返回“null”。
          • 如果值時undefined,則返回“undefined”。
          var value1=10;
          var value2=true;
          var value3=null;
          var value4;
          alert(String(value1)); //"10"
          alert(String(value2)); //"true"
          alert(String(value3)); //"null"
          alert(String(value4)); //"undefined"
          

          3、利用加號操作符

          要把某個值轉換為字符串,可以使用加號操作符把它與一個字符串(“”)加在一起。

          JavaScript中,所有的string類型(或者被稱為DOMString)都是使用UTF-16編碼的。

          MDN

          DOMString 是一個UTF-16字符串。由于JavaScript已經使用了這樣的字符串,所以DOMString 直接映射到 一個String

          null傳遞給接受DOMString的方法或參數時通常會把其stringifies為“null”。

          引出的Unicode中UTF-8與UTF-16編碼的詳細了解

          Unicode編碼

          Unicode(統一碼、萬國碼、單一碼)是計算機科學領域里的一項業界標準,包括字符集、編碼方案等。Unicode 是為了解決傳統的字符編碼方案的局限而產生的,它為每種語言中的每個字符設定了統一并且唯一的二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。1990年開始研發,1994年正式公布。

          通常Unicode編碼是通過2 Byte來表示一個字符的,如U+A12B,2 Byte的二進制表示方法結果就是1010(A)0001(1) 0010(2)1011(B)。

          需要注意的是:UTF是Unicode TransferFormat的縮寫,UTF-8和UTF-16都是把Unicode碼轉換成程序數據的一種編碼方式。

          UTF-8

          UTF-8(8-bit Unicode Transformation Format)是一種針對Unicode的可變長度字符編碼,又稱萬國碼。由Ken Thompson于1992年創建。現在已經標準化為RFC 3629。UTF-8用1到6個字節編碼Unicode字符(盡管如此,2003年11月UTF-8被RFC 3629重新規范,只能使用原來Unicode定義的區域,U+0000到U+10FFFF,也就是說最多4個字節)。用在網頁上可以統一頁面顯示中文簡體繁體及其它語言(如英文,日文,韓文)。

          UTF-8的來歷

          UTF-8的規范里充斥著這樣神秘的句子:“第一個位元組由110開始,接著的位元組由10開始”,“第一個位元組由1110開始,接著的位元組由10開始”。

          那么這到底是什么意思呢?為什么要這么做呢?

          我們先從二進制說起。我們都知道,一個字節是由8個二進制位構成的,最小就是0000 0000,最大就是1111 1111。那么一個字節所能表示的最多字符數就是2的8次方,也就是256。對于26個英文字母來說,大小寫全算上就是52個,再加上10個阿拉伯數字,62個字符,用可以表達256個不同字符的一個字節來存儲是足夠了。

          但是,我們中國的常用漢字就有3000多個,用一個只能表達256個字符的字節顯然是不夠存儲的。至少也需要有2個字節,1個字節是8個二進制位,2個字節就是16個二進制位,最多可以表達2的16次方,也就是256*256=65536。65536個字符足夠容納所有中國的漢字,外帶日語、韓語、阿拉伯語、稀其古怪語等等各種各樣的字符。所以這樣就產生了Unicode,因為它用2字節表示字符,所以更嚴格來講應該叫UCS-2,后來因為怪字符太多,2字節都不夠用了,所以又搞出來了一個4字節表示的方法,稱作UCS-4。不過現在對絕大多數人來講UCS-2已經是足夠了。

          Unicode本來是一個好東西,用2字節表示65536種字符,全人類皆大歡喜的事情。但是偏偏有一幫子西洋人,非要認為這個東西是一種浪費,說我們英文就最多只需要26個字母就夠了,1個字節就夠了,為什么要浪費2字節呢?比如說字母A就是0100 0001,這一個字節就夠了的東西,你弄2字節,非要在前面加8個0,0000 0000 0100 0001,這不是浪費嗎?我們就偏要用1字節表示英文。

          好吧,我們全人類只好做妥協,規定每個字節,只要看見0打頭的,就知道這是英文字母,這肯定不是漢字,只有看見1開頭的,才認為這是漢字。

          但是我們漢字用1個字節表示不下,那好辦,用2個1開頭的字符表示1個漢字。這樣本來16個二進制位,減去2個開頭的1,只剩下14個二進制位了,2的14次方就是16384個字符,對于中文來講,也是足夠用了。但是無奈他們還是想表達65536種字符,那怎么辦呢?就需要3個字節才能容納得下了,于是UTF-8粉墨登場。

          首先,首位為0的字符被占了,只要遇到0開頭的字符,就知道這是一個1字節的字符,不必再往后數了,直接拿來用就可以,最多表示128種字符,從0000 0000到0111 1111,也就是從0到127。

          接下來的事情就比較蹊蹺了。我們怎么用1開頭的字符既表示2字節,又表示3字節呢?假設我們只判斷首位的1,這顯然是不行的,沒有辦法區分,所以我們可以用10或者11開頭的字符來表示2字節,但是3字節又該以什么開頭?或者可以用10開頭表示2字節,用11開頭表示3字節?那么4字節的字符將來又該怎么辦?也許我們可以用110開頭表示3字節,用111開頭表示4字節?那么5字節6字節呢?似乎我們看到了一個規律:前面的1越多,代表字節數越多。

          這時候,看一下我們的第一種方案:用10開頭表示2字節,那么我們的一個字符將是

          10xx xxxx 10xx xxxx
          

          用110表示3字節,那么一個3字節的字符將是:

          110x xxxx 110x xxxx 110x xxxx
          

          這樣無疑是能區分得開的。但是4字節怎么辦?

          1110 xxxx 1110 xxxx 1110 xxxx 1110 xxxx
          

          嗎?這樣也能區分開,但似乎有點浪費。因為每個字節的前半扇都被無用的位占滿了,真正有意義的只有后面一半。

          或者我們干脆這樣做得了,我們來設計方案二:為了節省起見,所有后面的字符,我們統統都以10開頭,只要遇見10我們就知道它只是整個字符流的一部分,它肯定不是開頭,但是10這個開頭已經被我們剛剛方案一的2字節字符占用了,怎么辦?好辦,把2字節字符的開頭從10改成110,這樣它就肯定不會和10沖突了。于是2字節字符變成

          110x xxxx 10xx xxxx
          

          再往后順推,3字節字符變成

          1110 xxxx 10xx xxxx 10xx xxxx
          

          4字節字符變成

          1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
          

          好像比剛才的方案一有所節省呢!并且還帶來了額外的好處:如果我沒有見到前面的110或者1110開頭的字節,而直接見到了10開頭的字節,毫無疑問地可以肯定我遇到的不是一個完整字符的開頭,我可以直接忽略這個錯誤的字節,而直接找下一個正確字符的開頭。

          這個改良之后的方案二就是UTF-8!

          UTF-8表示的字符數

          現在,我們來算一下在UTF-8方案里,每一種字節可以表示多少種字符。

          1字節的字符,以0開頭的,0xxx xxxx,后面7個有效位,2的7次方,最多可以表示128種字符。

          2字節的字符,110x xxxx 10xx xxxx,數一數,11個x,所以是2的11次方,2的10次方是1024,11次方就是2048,很不幸,只能表示2048種字符,而我們的常用漢字就有3000多個,看來在這一區是放不下了,只好挪到3字節。

          3字節的字符,1110 xxxx 10xx xxxx 10xx xxxx,數一數,16個x,2的16次方,最多可以表示65536個字符,所以我們的漢字就放在這一區,所以在UTF-8方案里我們的漢字都是以3個字節表示的。

          所以這也就是這一張表的來歷:

          UTF-16

          UTF-16是Unicode字符編碼五層次模型的第三層:字符編碼表(Character Encoding Form,也稱為 "storage format")的一種實現方式。即把Unicode字符集的抽象碼位映射為16位長的整數(即碼元, 長度為2 Byte)的序列,用于數據存儲或傳遞。Unicode字符的碼位,需要1個或者2個16位長的碼元來表示,因此這是一個變長表示。

          起初,UTF-16任何字符對應的數字都用兩個字節來保。但是,65536顯然是不算太多的數字,用它來表示常用的字符是沒一點問題,足夠了。但如果加上很多特殊的就也不夠了。于是,從1996年開始又來了第二個版本,用四個字節表示所有字符。這樣就出現了UTF-8,UTF16,UTF-32。UTF-32就是把所有的字符都用32bit也就是4個字節來表示。然后UTF-8,UTF-16就視情況而定了,UTF-16可以選擇兩字節或四字節。

          UTF-16 并不是一個完美的選擇,它存在幾個方面的問題:

          1. UTF-16 能表示的字符數有 6 萬多,看起來很多,但是實際上目前 Unicode 5.0 收錄的字符已經達到 99024 個字符,早已超過 UTF-16 的存儲范圍;這直接導致 UTF-16 地位頗為尷尬——如果誰還在想著只要使用 UTF-16 就可以高枕無憂的話,恐怕要失望了
          2. UTF-16 存在大小端字節序問題,這個問題在進行信息交換時特別突出——如果字節序未協商好,將導致亂碼;如果協商好,但是雙方一個采用大端一個采用小端,則必然有一方要進行大小端轉換,性能損失不可避免(大小端問題其實不像看起來那么簡單,有時會涉及硬件、操作系統、上層軟件多個層次,可能會進行多次轉換)

          大小端轉換?

          1、因為utf8是變長編碼,而且是單字節為編碼單元,不存在誰在高位、誰在低位的問題,所以不存在順序問題!順便說一下解碼,由于utf8的首字節記 錄了總字節數(比如3個),所以讀取首字節后,再讀取后續字節(2個),然后進行解碼,得到完整的字節數,從而保證解碼也是正確的。

          2、utf16是變長編碼,使用1個16-bit編碼單元或者2個16-bit編碼單元,utf32是定長編碼,這里拿utf16舉例,在基本平面總是以2個字節為編碼單元, 鑒于“第一條”編碼單元與編碼單元之間的順序是正確的,問題只能在編碼單元內部中字節與字節的順序,由于硬件cpu的不同,編碼單元內部字節 與字節的順序不確定。假如cpu是大端序那么高位在前,如果cpu是小端序那么低位在前,為了區分,所以有了BOM(byte order mark),然后計 算機才能知道誰是高位,誰是低位,知道了高低位,從而能正確組裝,然后才能解碼正確。

          例如,一個“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。如果我們收到UTF-16字節流“594E”,那么這是“奎”還是“乙”?如果BOM 是大端序,那么代碼點就應該是594E,那么就是“奎”,如果BOM是小端序,那么代碼點就應該是4E59,就是“乙”了。

          綜上所述,因為utf8是單字節為編碼單元,在網絡傳輸時,不存在字節序列問題。在解碼時,由于首字節記錄了總字節數,所以能正確解碼。

          因為utf16是定長編碼,總是以2個字節為編碼單元,在網絡傳輸時,不存在字節序列問題。在解碼時,由于cpu硬件差異,存在字節序問題,所以通 過BOM來標記字節順序;

          另外,容錯性低有時候也是一大問題——局部的字節錯誤,特別是丟失或增加可能導致所有后續字符全部錯亂,錯亂后要想恢復,可能很簡單,也可能會 非常困難。(這一點在日常生活里大家感覺似乎無關緊要,但是在很多特殊環境下卻是巨大的缺陷)

          目前支撐我們繼續使用 UTF-16 的理由主要是考慮到它是雙字節的,在計算字符串長度、執行索引操作時速度很快。當然這些優點 UTF-32 都具有,但很多人畢竟還是覺得 UTF-32 太占空間了。

          UTF-8 也不完美,也存在一些問題:

          1. 文化上的不平衡——對于歐美地區一些以英語為母語的國家 UTF-8 簡直是太棒了,因為它和 ASCII 一樣,一個字符只占一個字節,沒有任何額外的存儲負擔;但是對于中日韓等國家來說,UTF-8 實在是太冗余,一個字符竟然要占用 3 個字節,存儲和傳輸的效率不但沒有提升,反而下降了。所以歐美人民常常毫不猶豫的采用 UTF-8,而我們卻老是要猶豫一會兒
          2. 變長字節表示帶來的效率問題——大家對 UTF-8 疑慮重重的一個問題就是在于其因為是變長字節表示,因此無論是計算字符數,還是執行索引操作效率都不高。為了解決這個問題,常常會考慮把 UTF-8 先轉換為 UTF-16 或者 UTF-32 后再操作,操作完畢后再轉換回去。而這顯然是一種性能負擔。

          UTF-8 的優點:

          1. 字符空間足夠大,未來 Unicode 新標準收錄更多字符,UTF-8 也能妥妥的兼容,因此不會再出現 UTF-16 那樣的尷尬
          2. 不存在大小端字節序問題,信息交換時非常便捷
          3. 容錯性高,局部的字節錯誤(丟失、增加、改變)不會導致連鎖性的錯誤,因為 UTF-8 的字符邊界很容易檢測出來,這是一個巨大的優點(正是為了實現這一點,咱們中日韓人民不得不忍受 3 字節 1 個字符的苦日子)

          大神如何選擇的呢?

          因為無論是 UTF-8 和 UTF-16/32 都各有優缺點,因此選擇的時候應當立足于實際的應用場景。例如在大神的習慣中,存儲在磁盤上或進行網絡交換時都會采用 UTF-8,而在程序內部進行處理時則轉換為 UTF-16/32。對于大多數簡單的程序來說,這樣做既可以保證信息交換時容易實現相互兼容,同時在內部處理時會比較簡單,性能也還算不錯。(基本上只要你的程序不是 I/O 密集型的都可以這么干,當然這只是大神粗淺的認識范圍內的經驗,很可能會被無情的反駁)


          主站蜘蛛池模板: 免费看AV毛片一区二区三区| 色屁屁一区二区三区视频国产| 冲田杏梨AV一区二区三区| 日韩精品一区二区三区中文精品| 日本免费一区二区三区最新| 国产亚洲一区二区三区在线| 国产精品免费综合一区视频| 无码一区二区三区免费| 国产精品伦子一区二区三区| 国产人妖视频一区二区| 国产美女av在线一区| 无码少妇一区二区浪潮av| 亚洲国产AV无码一区二区三区| 无码aⅴ精品一区二区三区浪潮 | 毛片一区二区三区无码| 无码精品国产一区二区三区免费| 国产一区二区三区免费观在线 | 交换国产精品视频一区| 免费av一区二区三区| 国产视频一区在线观看| 射精专区一区二区朝鲜| 国产日韩一区二区三区在线观看| 亚洲线精品一区二区三区| 人妻无码一区二区三区四区| 午夜视频一区二区| 精品无码综合一区| 日韩亚洲一区二区三区| av无码免费一区二区三区| 伊人色综合网一区二区三区 | 亚洲午夜在线一区| 亚洲精品精华液一区二区| 日本精品夜色视频一区二区| 亚洲AV无码一区二区三区国产 | 精品日韩在线视频一区二区三区 | 麻豆视传媒一区二区三区| 国产精品 一区 在线| 亚洲一区二区三区久久久久| 国产精品一区二区在线观看| 亚洲国产精品乱码一区二区| 欧美亚洲精品一区二区| 亚洲综合国产一区二区三区|