精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

重構 - 改善代碼的各方面問題

開發 前端
重構不是對以前代碼的全盤否定,而是利用更好的方式,寫出更好,更有維護性代碼。不斷的追求與學習,才有更多的進步。

[[227146]]

重構不是對以前代碼的全盤否定,而是利用更好的方式,寫出更好,更有維護性代碼。不斷的追求與學習,才有更多的進步。

1.前言

做前端開發有一段時間了,在這段時間里面,對于自己的要求,不僅僅是項目能完成,功能正常使用這一層面上。還盡力的研究怎么寫出優雅的代碼,性能更好,維護性更強的代碼,通俗一點就是重構。這篇文章算是我一個小記錄,在此分享一下。該文章主要針對介紹,例子也簡單,深入復雜的例子等以后有適合的實例再進行寫作分享。如果大家對怎么寫出優雅的代碼,可維護的代碼,有自己的見解,或者有什么重構的實力,歡迎指點評論。

關于重構,準備寫一個系列的文章,不定時更新,主要針對以下方案:邏輯混亂重構,分離職責重構,添加擴展性重構,簡化使用重構,代碼復用重構。其中會穿插以下原則:單一職責原則,最少知識原則,開放-封閉原則。如果大家對重構有什么好的想法,或者有什么好的實例,歡迎留言評論,留下寶貴的建議。

2.什么是重構

首先,重構不是重寫。重構大概的意思是在不影響項目的功能使用前提下,使用一系列的重構方式,改變項目的內部結構。提高項目內部的可讀性,可維護性。

無論是什么項目,都有一個從簡單到復雜的一個迭代過程。在這個過程里面,在不影響項目的使用情況下,需要不斷的對代碼進行優化,保持或者增加代碼的可讀性,可維護性。這樣一來,就可以避免在團隊協作開發上需要大量的溝通,交流。才能加入項目的開發中。

3.為什么重構

衣服臟了就洗,破了就補,不合穿就扔。

隨著業務需求的不斷增加,變更,舍棄,項目的代碼也難免會出現瑕疵,這就會影響代碼的可讀性,可維護性,甚至影響項目的性能。而重構的目的,就是為了解決這些瑕疵,保證代碼質量和性能。但是前提是不能影響項目的使用。

至于重構的原因,自己總結了一下,大概有以下幾點

  1.     函數邏輯結構混亂,或因為沒注釋原因,連原代碼寫作者都很難理清當中的邏輯。
  2.     函數無擴展性可言,遇到新的變化,不能靈活的處理。
  3.     因為對象強耦合或者業務邏輯的原因,導致業務邏輯的代碼巨大,維護的時候排查困難。
  4.     重復代碼太多,沒有復用性。
  5.     隨著技術的發展,代碼可能也需要使用新特性進行修改。
  6.     隨著學習的深入,對于以前的代碼,是否有著更好的一個解決方案。
  7.     因為代碼的寫法,雖然功能正常使用,但是性能消耗較多,需要換方案進行優化

4.何時重構

在合適的時間,在合適的事情

在我的理解中,重構可以說是貫穿整一個項目的開發和維護周期,可以當作重構就是開發的一部分。通俗講,在開發的任何時候,只要看到代碼有別扭,激發了強迫癥,就可以考慮重構了。只是,重構之前先參考下面幾點。

  • 首先,重構是需要花時間去做的一件事。花的時間可能比之前的開發時間還要多。
  • 其次,重構是為了把代碼優化,前提是不能影響項目的使用。
  • ***,重構的難度大小不一,可能只是稍微改動,可能難度比之前開發還要難。

基于上面的幾點,需要大家去評估是否要進行重構。評估的指標,可以參考下面幾點

  • 數量: 需要重構的代碼是否過多。
  • 質量: 可讀性,可維護性,代碼邏輯復雜度,等問題,對代碼的質量影響是否到了一個難以忍受的地步。
  • 時間: 是否有充裕的時間進行重構和測試。
  • 效果: 如果重構了代碼,得到哪些改善,比如代碼質量提高了,性能提升了,更好的支持后續功能等。

5.怎么重構

選定目標,針對性出擊

怎么重構,這個就是具體情況,具體分析了。如同“為什么重構一樣”。發現代碼有什么問題就針對什么情況進行改進。

重構也是寫代碼,但是不止于寫,更在于整理和優化。如果說寫代碼需要一個‘學習--了解-熟練’的過程,那么重構就需要一個‘學習-感悟-突破-熟練’的過程。

針對重構的情況,下面簡單的用幾個例子進行說明

5-1.函數無擴展性

如下面一個例子,在我一個庫的其中一個 API

 

  1. //檢測字符串  
  2. //checkType('165226226326','mobile' 
  3. //result:false  
  4. let checkType=function(str, type) {  
  5.     switch (type) {  
  6.         case 'email' 
  7.             return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);  
  8.         case 'mobile' 
  9.             return /^1[3|4|5|7|8][0-9]{9}$/.test(str);  
  10.         case 'tel' 
  11.             return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str);  
  12.         case 'number' 
  13.             return /^[0-9]$/.test(str);  
  14.         case 'english' 
  15.             return /^[a-zA-Z]+$/.test(str);  
  16.         case 'text' 
  17.             return /^\w+$/.test(str);  
  18.         case 'chinese' 
  19.             return /^[\u4E00-\u9FA5]+$/.test(str);  
  20.         case 'lower' 
  21.             return /^[a-z]+$/.test(str);  
  22.         case 'upper'
  23.             return /^[A-Z]+$/.test(str);  
  24.         default 
  25.             return true 
  26.     }  

這個 API 看著沒什么毛病,能檢測常用的一些數據。但是有以下兩個問題。

  1. 但是如果想到添加其他規則的呢?就得在函數里面增加 case 。添加一個規則就修改一次!這樣違反了開放-封閉原則(對擴展開放,對修改關閉)。而且這樣也會導致整個 API 變得臃腫,難維護。
  2. 還有一個問題就是,比如A頁面需要添加一個金額的校驗,B頁面需要一個日期的校驗,但是金額的校驗只在A頁面需要,日期的校驗只在B頁面需要。如果一直添加 case 。就是導致A頁面把只在B頁面需要的校驗規則也添加進去,造成不必要的開銷。B頁面也同理。

建議的方式是給這個 API 增加一個擴展的接口

 

  1. let checkType=(function(){  
  2.     let rules={  
  3.         email(str){  
  4.             return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);  
  5.         },  
  6.         mobile(str){  
  7.             return /^1[3|4|5|7|8][0-9]{9}$/.test(str);  
  8.         },  
  9.         tel(str){  
  10.             return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str);  
  11.         }, 
  12.         number(str){  
  13.             return /^[0-9]$/.test(str);  
  14.         },  
  15.         english(str){  
  16.             return /^[a-zA-Z]+$/.test(str);  
  17.         },  
  18.         text(str){  
  19.             return /^\w+$/.test(str);  
  20.         },  
  21.         chinese(str){  
  22.             return /^[\u4E00-\u9FA5]+$/.test(str);  
  23.         },  
  24.         lower(str){  
  25.             return /^[a-z]+$/.test(str);  
  26.         },  
  27.         upper(str){  
  28.             return /^[A-Z]+$/.test(str);  
  29.         }  
  30.     };  
  31.     //暴露接口  
  32.     return {  
  33.         //校驗  
  34.         check(str, type){  
  35.             return rules[type]?rules[type](str):false 
  36.         },  
  37.         //添加規則  
  38.         addRule(type,fn){  
  39.             rules[type]=fn;  
  40.         }  
  41.     }  
  42. })();  
  43.  
  44. //調用方式  
  45. //使用mobile校驗規則  
  46. console.log(checkType.check('188170239','mobile'));  
  47. //添加金額校驗規則  
  48. checkType.addRule('money',function (str) {  
  49.     return /^[0-9]+(.[0-9]{2})?$/.test(str)  
  50. });  
  51. //使用金額校驗規則  
  52. console.log(checkType.check('18.36','money')); 

上面的代碼,是多了一些,但是理解起來也沒怎么費勁,而且拓展性也有了。

上面這個改進其實是使用了策略模式(把一系列的算法進行封裝,使算法代碼和邏輯代碼可以相互獨立,并且不會影響算法的使用)進行改進的。策略模式的概念理解起來有點繞,但是大家看著代碼,應該不繞。

這里展開講一點,在功能上來說,通過重構,給函數增加擴展性,這里實現了。但是如果上面的 checkType是一個開源項目的 API ,重構之前調用方式是:checkType('165226226326','phone') 。重構之后調用方式是: checkType.check('188170239','phone') ;或者 checkType.addRule() ;。如果開源項目的作者按照上面的方式重構,那么之前使用了開源項目的 checkType 這個 API 的開發者,就可能悲劇了,因為只要開發者一更新這個項目版本,就有問題。因為上面的重構沒有做向下兼容。

如果要向下兼容,其實也不難。加一個判斷而已。

 

  1. let checkType=(function(){  
  2.     let rules={  
  3.         email(str){  
  4.             return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);  
  5.         },  
  6.         mobile(str){  
  7.             return /^1[3|4|5|7|8][0-9]{9}$/.test(str);  
  8.         },  
  9.         tel(str){  
  10.             return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str);  
  11.         },  
  12.         number(str){  
  13.             return /^[0-9]$/.test(str);  
  14.         },  
  15.         english(str){  
  16.             return /^[a-zA-Z]+$/.test(str);  
  17.         },  
  18.         text(str){  
  19.             return /^\w+$/.test(str);  
  20.         },  
  21.         chinese(str){  
  22.             return /^[\u4E00-\u9FA5]+$/.test(str);  
  23.         },  
  24.         lower(str){  
  25.             return /^[a-z]+$/.test(str);  
  26.         },  
  27.         upper(str){  
  28.             return /^[A-Z]+$/.test(str);  
  29.         }  
  30.     };  
  31.     //暴露接口  
  32.     return function (str,type){  
  33.         //如果type是函數,就擴展rules,否則就是驗證數據  
  34.         if(type.constructor===Function){  
  35.             rules[str]=type;  
  36.         }  
  37.         else 
  38.             return rules[type]?rules[type](str):false 
  39.         }  
  40.     }  
  41. })();  
  42.  
  43. console.log(checkType('188170239','mobile'));  
  44.  
  45. checkType('money',function (str) {  
  46.     return /^[0-9]+(.[0-9]{2})?$/.test(str)  
  47. });  
  48. //使用金額校驗規則  
  49. console.log(checkType('18.36','money')); 

這樣運行能正常,也有擴展性性,但是對于代碼潔癖的來說,這樣寫法不優雅。因為 checkType 違反了函數單一原則。一個函數負責過多的職責可能會導致以后不可估量的問題,使用方面也很讓人疑惑。

面對這樣的情況,就個人而言,了解的做法是:保留 checkType ,不做任何修改,在項目里面增加一個新的 API ,比如 checkTypOfString ,把重構的代碼寫到 checkTypOfString 里面。通過各種方式引導開發者少舊 checkType ,多用 checkTypOfString 。之后的項目迭代里面,合適的時候廢棄 checkType 。

5-2.函數違反單一原則

函數違反單一原則***一個后果就是會導致邏輯混亂。如果一個函數承擔了太多的職責,不妨試下:函數單一原則 -- 一個函數只做一件事。

如下例子

 

  1. //現有一批的錄入學生信息,但是數據有重復,需要把數據進行去重。然后把為空的信息,改成保密。  
  2. let students=[  
  3.     {  
  4.         id:1,  
  5.         name:'守候' 
  6.         sex:'男' 
  7.         age:'' 
  8.     },  
  9.     {  
  10.         id:2,  
  11.         name:'浪跡天涯' 
  12.         sex:'男' 
  13.         age:''  
  14.     },  
  15.     {  
  16.         id:1,  
  17.         name:'守候' 
  18.         sex:'' 
  19.         age:''  
  20.     },  
  21.     {  
  22.         id:3,  
  23.         name:'鴻雁' 
  24.         sex:'' 
  25.         age:'20'  
  26.     }  
  27. ];  
  28.  
  29. function handle(arr) {  
  30.     //數組去重  
  31.     let _arr=[],_arrIds=[];  
  32.     for(let i=0;i<arr.length;i++){  
  33.         if(_arrIds.indexOf(arr[i].id)===-1){  
  34.             _arrIds.push(arr[i].id);  
  35.             _arr.push(arr[i]);  
  36.         }  
  37.     }  
  38.     //遍歷替換  
  39.     _arr.map(item=>{  
  40.         for(let key in item){  
  41.             if(item[key]===''){  
  42.                 item[key]='保密' 
  43.             }  
  44.         }  
  45.     });  
  46.     return _arr;  
  47.  
  48. console.log(handle(students)) 

運行結果沒有問題,但是大家想一下,如果以后,如果改了需求,比如,學生信息不會再有重復的記錄,要求把去重的函數去掉。這樣一來,就是整個函數都要改了。還影響到下面的操作流程。相當于了改了需求,整個方法全跪。城門失火殃及池魚。

下面使用單一原則構造一下

 

  1. let handle={  
  2.     removeRepeat(arr){  
  3.         //數組去重  
  4.         let _arr=[],_arrIds=[];  
  5.         for(let i=0;i<arr.length;i++){  
  6.             if(_arrIds.indexOf(arr[i].id)===-1){  
  7.                 _arrIds.push(arr[i].id);  
  8.                 _arr.push(arr[i]);  
  9.             }  
  10.         }  
  11.         return _arr;  
  12.     },  
  13.     setInfo(arr){  
  14.         arr.map(item=>{  
  15.             for(let key in item){  
  16.                 if(item[key]===''){  
  17.                     item[key]='保密' 
  18.                 }  
  19.             }  
  20.         });  
  21.         return arr;  
  22.     }  
  23. };  
  24. students=handle.removeRepeat(students);  
  25. students=handle.setInfo(students);  
  26. console.log(students); 

結果一樣,但是需求改下,比如不需要去重,把代碼注釋或者直接刪除就好。這樣相當于把函數的職責分離了,而且職責之前互不影響。中間去除那個步驟不會影響下一步。

 

  1. //students=handle.removeRepeat(students);  
  2. students=handle.setInfo(students);  
  3. console.log(students); 

5-3.函數寫法優化

這種情況就是,對于以前的函數,在不影響使用的情況下,現在有著更好的實現方式。就使用更好的解決方案,替換以前的解決方案。

比如下面的需求,需求是群里一個朋友發出來的,后來引發的一些討論。給出一個20180408000000字符串,formatDate函數要處理并返回2018-04-08 00:00:00。

以前的解法

 

  1. let _dete='20180408000000'  
  2. function formatStr(str){  
  3.     return str.replace(/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/, "$1-$2-$3 $4:$5:$6" 
  4.  
  5. formatStr(_dete);  
  6. //"2018-04-08 00:00:00" 

后來研究了這樣的解法。這個方式就是根據x的位置進行替換填充數據,不難理解

 

  1. let _dete='20180408000000'  
  2. function formatStr(str,type){  
  3.     let _type=type||"xxxx-xx-xx xx:xx:xx" 
  4.     for(let i = 0; i < str.length; i++){  
  5.         _type = _type.replace('x', str[i]);  
  6.     }  
  7.     return _type;  
  8.  
  9. formatStr(_dete);  
  10. result:"2018-04-08 00:00:00" 

在之后的幾天,在掘金一篇文章(那些優雅靈性的JS代碼片段,感謝提供的寶貴方式)的評論里面發現更好的實現方式,下面根據上面的需求自己進行改造。

 

  1. let _dete='20180408000000'  
  2. function formatStr(str,type){  
  3.     let i = 0,_type = type||"xxxx-xx-xx xx:xx:xx" 
  4.     return _type .replace(/x/g, () => str[i++])  
  5.  
  6. formatStr(_dete);  
  7. result:"2018-04-08 00:00:00" 

5-4.代碼復用

上面幾個例子都是js的,說下與html沾邊一點的兩個例子--vue數據渲染。

    下面代碼中,payChannelEn2Cn addZero formatDateTime函數都是在vue的methods里面。大家注意。

以前寫法

 

  1. <span v-if="cashType==='cash'">現金</span>  
  2. <span v-else-if="cashType==='check'">支票</span>  
  3. <span v-else-if="cashType==='draft'">匯票</span>  
  4. <span v-else-if="cashType==='zfb'">支付寶</span>  
  5. <span v-else-if="cashType==='wx_pay'">微信支付</span>  
  6. <span v-else-if="cashType==='bank_trans'">銀行轉賬</span>  
  7. <span v-else-if="cashType==='pre_pay'">預付款</span> 

這樣寫的問題在于,首先是代碼多,第二是如果項目有10個地方這樣渲染數據,如果渲染的需求變了。比如銀行轉賬的值從 bank_trans 改成 bank ,那么就得在項目里面修改10次。時間成本太大。

后來就使用了下面的寫法,算是一個小重構吧

 

  1. <span>{{payChannelEn2Cn(cashType)}}</span> 

payChannelEn2Cn 函數,輸出結果

 

  1. payChannelEn2Cn(tag){  
  2.     let _obj = {  
  3.         'cash''現金' 
  4.         'check''支票' 
  5.         'draft''匯票' 
  6.         'zfb''支付寶' 
  7.         'wx_pay''微信支付' 
  8.         'bank_trans''銀行轉賬' 
  9.         'pre_pay''預付款'  
  10.     };  
  11.     return _obj[tag];  

還有一個例子就是時間戳轉時間的寫法。原理一樣,只是代碼不同。下面是原來的代碼。

 

  1. <span>{{new Date(payTime).toLocaleDateString().replace(/\//g, '-')}}   
  2. {{addZero(new Date(payTime).getHours())}}:  
  3. {{addZero(new Date(payTime).getMinutes())}}:  
  4. {{addZero(new Date(payTime).getSeconds())}}</span> 

addZero時間補零函數

 

  1. Example:3->03  
  2. addZero(i){  
  3.     if (i < 10) {  
  4.         i = "0" + i;  
  5.     }  
  6.     return i;  

問題也和上面的一樣,這里就不多說了,就寫重構后的代碼

 

  1. <span>{{formatDateTime(payTime)}} </span> 

formatDateTime函數,格式化字符串

 

  1. formatDateTime(dateTime){  
  2.     return `${new Date(payTime).toLocaleDateString().replace(/\//g, '-')} ${this.addZero(new Date(payTime).getHours())}:${this.addZero(new Date(payTime).getMinutes())}:${this.addZero(new Date(payTime).getSeconds())}`;  

 

可能很多人看到這里,覺得重構很簡單,這樣想是對的,重構就是這么簡單。但是重構也難,因為重構一步登天,需要一個逐步的過程,甚至可以說重構就是一次次的小改動,逐步形成一個質變的過程。如何保證每一次的改動都是有意義的改善代碼;如何保證每一次的改動都不會影響到項目的正常使用;如果發現某次改動沒有意義,或者改動了反而讓代碼更糟糕的時候,可以隨時停止或回滾代碼,這些才是重構的難點。

6.小結

 

關于重構就說到這里了,該文章主要是介紹重構,例子方面都是很簡單的一些例子。目的是為了好些理解重構的一些概念。關于重構,可能很復雜,可能很簡單。怎么重構也是具體情況,具體分析,重構也沒有標準的答案。以后,如果有好的例子,我會***時間分享,給大家具體情況,具體分析的講述:為什么重構,怎么重構。 

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2010-07-09 14:46:56

2011-12-12 10:06:14

解析網站

2023-08-27 14:48:19

開源辦公套件應用程序

2013-05-13 09:36:28

ClouderaImpala 1.0Hadoop

2009-10-16 10:44:17

2014-10-27 09:51:19

Web設計HTML

2018-11-26 08:23:36

物聯網客戶體驗IOT

2021-08-03 08:13:48

重構API代碼

2019-09-12 08:00:00

Visual Stud軟件開發

2021-05-31 19:04:50

低代碼平臺低代碼開發

2024-12-20 08:00:00

2024-09-05 10:17:34

2012-02-23 00:22:55

2010-10-20 09:25:49

網絡成本

2012-07-27 10:30:12

重構

2010-04-02 12:24:08

2011-07-06 09:40:24

云計算紅帽

2010-01-23 20:57:48

2025-03-25 09:12:00

LIMAI模型

2022-07-25 15:21:50

Java編程語言開發
點贊
收藏

51CTO技術棧公眾號

青青操免费在线视频| av中文字幕网址| 五月天婷婷社区| 日本美女一区二区| 久久夜精品va视频免费观看| wwwxxxx在线观看| 蜜桃视频www网站在线观看| 久久久精品国产99久久精品芒果| 成人黄色短视频在线观看 | 国产精品每日更新在线播放网址| 91网站在线免费观看| 亚洲天堂视频网站| 亚洲自拍偷拍网| 日韩成人中文字幕在线观看| 日本不卡一区二区在线观看| 91超碰免费在线| 国产精品久久免费看| 国产精品自拍首页| 国产精品玖玖玖| 欧美亚洲网站| 欧美激情奇米色| 极品蜜桃臀肥臀-x88av| 国产欧美啪啪| 欧美一区二区三区四区久久| www.亚洲天堂网| 图片区小说区亚洲| 中文字幕av一区二区三区高| 久久伊人资源站| 国产色片在线观看| 青娱乐精品在线视频| 91国内产香蕉| 妺妺窝人体色www婷婷| 第一会所亚洲原创| 亚洲欧美激情四射在线日| 久久久久中文字幕亚洲精品| 日本免费一区二区三区等视频| 欧美日韩激情视频| 免费在线看黄色片| 最新国产在线拍揄自揄视频| 国产精品久久久久久久第一福利 | 欧美亚洲日本网站| 免费在线观看黄色av| 五月天综合网站| 中文字幕亚洲专区| 亚洲国产日韩一区无码精品久久久| 国产 日韩 欧美 综合 一区| 日韩无一区二区| 亚洲av无日韩毛片久久| 国产欧美自拍| 欧美日韩在线不卡| 亚洲另类第一页| 成人精品三级| 欧美又粗又大又爽| 天天干在线影院| 欧美黄色网页| 在线一区二区三区四区五区| 日日碰狠狠躁久久躁婷婷| 国产亚洲成av人片在线观看| 午夜伦欧美伦电影理论片| 久操手机在线视频| 搞黄网站在线看| 亚洲图片欧美视频| 日本中文字幕亚洲| 爱啪视频在线观看视频免费| 欧美日韩另类在线| 国产午夜伦鲁鲁| 成人免费直播| 日本精品一区二区三区四区的功能| 99蜜桃臀久久久欧美精品网站| 亚洲插插视频| 欧美亚洲动漫另类| 日韩在线一区视频| 国产95亚洲| 精品国产三级电影在线观看| chinese麻豆新拍video| 少妇精品久久久一区二区三区| 亚洲全黄一级网站| 又色又爽的视频| 亚洲国产精品日韩专区av有中文| 美女久久久久久久| 久久精品亚洲无码| 久久精品123| 国产精品夜色7777狼人| 97免费观看视频| 处破女av一区二区| 国产亚洲精品久久飘花| 国产精品四虎| 国产精品福利一区| avav在线播放| 极品美女一区| 3atv一区二区三区| av黄色一级片| 成人久久一区| 欧美激情久久久久久| 欧美亚洲精品天堂| 久久se精品一区二区| 99久久99| 国产成人天天5g影院在线观看| 国产精品嫩草久久久久| 日韩 欧美 视频| 日韩影片中文字幕| 欧美一区二区三区四区高清| 菠萝菠萝蜜网站| 久久综合88| 久久久久亚洲精品成人网小说| 欧产日产国产69| 国产乱子伦视频一区二区三区| 极品日韩久久| 免费在线观看av网站| 天天综合色天天综合| 中文字幕 日韩 欧美| 欧美激情极品| 免费不卡在线观看av| 久久亚洲精品石原莉奈| 国产精一品亚洲二区在线视频| 久久国产欧美精品| www久久日com| 欧美性受xxxx| 国产精品久久久免费观看| 中出一区二区| 国产精品爽爽爽| 日本一区视频| 亚洲国产精品一区二区尤物区| www.日本一区| 中文字幕伦av一区二区邻居| 色中色综合影院手机版在线观看| 亚洲男人天堂网址| 99免费精品视频| 成年丰满熟妇午夜免费视频| 久久亚洲人体| 在线激情影院一区| av中文在线播放| 成人做爰69片免费看网站| 一区二区三区日韩视频| 欧美暴力调教| 亚洲欧美日韩久久久久久| 国产稀缺真实呦乱在线| 国产精品综合一区二区| 亚洲激情图片| 91精品影视| 亚洲欧美综合图区| 丁香六月婷婷综合| 久久久综合九色合综国产精品| 日韩一级性生活片| 国产suv精品一区| 久久久久久久久久久免费 | 亚洲精品mp4| 日本三级片在线观看| 国产传媒久久文化传媒| 99热都是精品| 老司机亚洲精品一区二区| 久久精视频免费在线久久完整在线看| 自拍偷拍色综合| 欧美国产精品中文字幕| 亚洲激情在线观看视频| 欧美一区二区三| 国产精品久久视频| 尤物网在线观看| 欧美午夜一区二区三区| 手机毛片在线观看| 麻豆精品视频在线观看免费 | 污污免费在线观看| 亚洲图片在线| 久久精品magnetxturnbtih| а√天堂中文在线资源8| 日韩av一区在线| 极品国产91在线网站| 国产女人18毛片水真多成人如厕 | 国内一区二区在线| 欧美精品久久96人妻无码| 日韩一级淫片| 91成人精品网站| 撸视在线观看免费视频| 欧美唯美清纯偷拍| 男人操女人的视频网站| 成人综合在线视频| 日本精品久久久久中文字幕| 日韩欧美网站| 古典武侠综合av第一页| 国产直播在线| 中文字幕亚洲自拍| 亚洲a视频在线| 色猫猫国产区一区二在线视频| 91麻豆制片厂| 成人综合婷婷国产精品久久蜜臀| 欧美韩国日本在线| 99久久九九| 国产精品一级久久久| 欧美大片1688| 欧美精品在线网站| 日本福利片在线| 欧美精品自拍偷拍| 日本熟女一区二区| 中国av一区二区三区| av电影在线播放| 日韩不卡一区二区| 91精品国产毛片武则天| 亚洲人挤奶视频| 亚洲在线第一页| 粉嫩一区二区| 欧美精品videosex极品1| 黄色大片在线免费观看| 日韩一区二区高清| 国产情侣呻吟对白高潮| 亚洲午夜久久久久| 亚洲色图日韩精品| 不卡一卡二卡三乱码免费网站| xxxx一级片| 亚洲高清在线| 国产日韩视频在线播放| 蜜桃a∨噜噜一区二区三区| 成人日韩在线电影| 日韩免费小视频| 国内精品久久久久影院 日本资源 国内精品久久久久伊人av | 欧美性生交大片| 久久综合九色欧美综合狠狠 | 久久综合久久鬼色中文字| 57pao国产成永久免费视频| 亚洲一区二区动漫| 精品人妻人人做人人爽| 91亚洲一区| 日本精品一区二区| 日本天堂一区| 国产成人精品一区二区三区福利| 欧美视频在线视频精品| 人人做人人澡人人爽欧美| aaa在线播放视频| 欧美成人午夜激情在线| av播放在线| 91视频xxxx| 久久青草精品视频免费观看| 极品白浆推特女神在线观看| 亚洲精品一区二区三区精华液 | 欧美成人精品3d动漫h| 一级黄色片在线| 欧美视频在线不卡| 日本中文字幕第一页| 亚洲国产精品综合小说图片区| 亚洲色婷婷一区二区三区| 国产精品国产三级国产| 欧美激情 一区| 国产人成亚洲第一网站在线播放| 37p粉嫩大胆色噜噜噜| 久久一留热品黄| 真人bbbbbbbbb毛片| 97精品久久久午夜一区二区三区| 亚洲午夜久久久久久久久| 国产精品一区二区免费不卡| 成人免费黄色av| 国产乱码精品一品二品| 搡的我好爽在线观看免费视频| 久国产精品韩国三级视频| 色啦啦av综合| 国产一区二区免费看| 国产精品三级美女白浆呻吟| ****av在线网毛片| 午夜精品一区二区三区在线视频| 超碰资源在线| 青草热久免费精品视频| 亚洲承认视频| 国产精品直播网红| 国产精品igao视频网网址不卡日韩| 成人精品aaaa网站| 在线播放一区二区精品视频| 高清不卡日本v二区在线| 欧美三级午夜理伦三级小说| 精品卡一卡二| 国内成人精品| 黄色www在线观看| 激情视频一区| 久久人妻精品白浆国产 | 国产精品91久久| 国产欧美自拍| 成人午夜电影免费在线观看| 大奶在线精品| 视频一区二区综合| 亚洲草久电影| 日本韩国欧美在线观看| 日韩制服丝袜av| 国产91在线免费观看| 99精品欧美一区| 欧美成人久久久免费播放| 亚洲精品日产精品乱码不卡| 日韩精品视频免费看| 在线精品观看国产| 国产wwwwwww| 亚洲精品视频中文字幕| 免费一级肉体全黄毛片| 欧美三级特黄| 午夜在线视频免费观看| 一本色道精品久久一区二区三区| 久久黄色免费看| 国产精品自拍毛片| 在线国产视频一区| 亚洲视频你懂的| 91在线视频在线观看| 欧美高清精品3d| 免费观看国产精品| 中文字幕日韩高清| 国产一二在线播放| 91亚洲精品一区二区| 一本色道久久综合狠狠躁的番外| 久久99国产精品一区| 性欧美videos另类喷潮| 日本在线观看视频一区| 久久精品夜色噜噜亚洲a∨| 九九热国产精品视频| 欧美无砖专区一中文字| 天天干天天操av| 久久国产精品网站| 日本成人福利| 精品欧美国产| 午夜精品网站| 黄色一级片免费的| 国产性天天综合网| 精品无码免费视频| 欧美一区二区三区在线观看视频| 久久久久久青草| 韩国精品美女www爽爽爽视频| 高清成人在线| 欧美日韩综合久久| 亚洲精品1区2区| 国产又黄又嫩又滑又白| 国产精品久久久久9999吃药| 无码视频在线观看| 亚洲开心激情网| 免费h视频在线观看| 国产精品theporn88| 欧美va天堂| 欧美一级小视频| 亚洲欧洲99久久| 天天干天天插天天射| 亚洲欧美日韩综合| 涩涩涩在线视频| 国产一区二区自拍| 91久久黄色| 99精品一区二区三区无码吞精| 亚洲综合激情网| 亚洲AV无码成人片在线观看| 欧美xxxx综合视频| 国产精品免费精品自在线观看| 伊人久久青草| 九色|91porny| 性欧美videos| 欧美一区二区视频在线观看 | 日韩 欧美 高清| 91视频精品在这里| 特黄视频免费看| 亚洲乱码一区av黑人高潮 | 欧美成熟视频| 日韩一区二区免费在线观看| 免费福利在线视频| 国产大片精品免费永久看nba| 国产乱码精品一区二区三区四区| www.日日操| 日本一区二区动态图| 中文字幕1区2区3区| 日韩中文字幕av| 成人短视频软件网站大全app| 国产大尺度在线观看| 国产aⅴ精品一区二区三区色成熟| 9999热视频| 精品日韩一区二区三区免费视频| 7777kkk亚洲综合欧美网站| 狠狠色伊人亚洲综合网站色| 性欧美videos另类喷潮| 欧美福利第一页| 91精品在线一区二区| 男女视频在线| 欧美激情一区二区三区在线视频 | 国产精品成人观看视频国产奇米| 国产精品美女久久久久久不卡| 亚洲色图久久久| 一区二区在线电影| 性感美女福利视频| 国产精品久久av| 欧美精品黄色| 黄色a一级视频| 欧美日韩在线三区| 天堂av在线电影| 欧美激情第六页| 国产麻豆精品久久一二三| 久久夜色精品亚洲| 伊人精品在线观看| 欧美成年网站| 美女福利视频在线| 亚洲欧美日韩国产另类专区| 天天操天天干天天插| 国产欧美va欧美va香蕉在| 精品999网站| 午夜黄色福利视频| 精品国产污网站| 久久国产三级| 欧美高清中文字幕| 欧美国产一区在线| 亚洲男人第一天堂| 91精品久久久久久久久久入口| 亚洲高清免费| 欧美激情精品久久久久久免费| 日韩国产精品一区|