亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

JS開發常用工具函數(小結)

2024-05-06 16:53:03
字體:
來源:轉載
供稿:網友

1、isStatic:檢測數據是不是除了symbol外的原始數據

function isStatic(value) {  return(    typeof value === 'string' ||    typeof value === 'number' ||    typeof value === 'boolean' ||    typeof value === 'undefined' ||    value === null  )}

2、isPrimitive:檢測數據是不是原始數據

function isPrimitive(value) {  return isStatic(value) || typeof value === 'symbol'}

3、isObject:判斷數據是不是引用類型的數據 (例如: arrays, functions, objects, regexes, new Number(0),以及 new String(''))

function isObject(value) {   let type = typeof value;   return value != null && (type == 'object' || type == 'function');}

4、isObjectLike:檢查 value 是否是 類對象。 如果一個值是類對象,那么它不應該是 null,而且 typeof 后的結果是 "object"

function isObjectLike(value) {   return value != null && typeof value == 'object';}

5、getRawType:獲取數據類型,返回結果為 Number、String、Object、Array等

function getRawType(value) {  return Object.prototype.toString.call(value).slice(8, -1)}//getoRawType([]) ==> Array

6、isPlainObject:判斷數據是不是Object類型的數據

function isPlainObject(obj) {  return Object.prototype.toString.call(obj) === '[object Object]'}

7、isArray:判斷數據是不是數組類型的數據

function isArray(arr) {  return Object.prototype.toString.call(arr) === '[object Array]'}

將isArray掛載到Array上

Array.isArray = Array.isArray || isArray;

8、isRegExp:判斷數據是不是正則對象

function isRegExp(value) {  return Object.prototype.toString.call(value) === '[object RegExp]'}

9、isDate:判斷數據是不是時間對象

function isDate(value) {  return Object.prototype.toString.call(value) === '[object Date]'}

10、isNative:判斷 value 是不是瀏覽器內置函數

內置函數toString后的主體代碼塊為 [native code] ,而非內置函數則為相關代碼,所以非內置函數可以進行拷貝(toString后掐頭去尾再由Function轉)

function isNative(value) {  return typeof value === 'function' && /native code/.test(value.toString())}

11、isFunction:檢查 value 是不是函數

function isFunction(value) {  return Object.prototype.toString.call(value) === '[object Function]'}

12、isLength:檢查 value 是否為有效的類數組長度

function isLength(value) {   return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= Number.MAX_SAFE_INTEGER;}

13、isArrayLike:檢查 value 是否是類數組

如果一個值被認為是類數組,那么它不是一個函數,并且value.length是個整數,大于等于 0,小于或等于 Number.MAX_SAFE_INTEGER。這里字符串也將被當作類數組

function isArrayLike(value) {   return value != null && isLength(value.length) && !isFunction(value);}

14、isEmpty:檢查 value 是否為空

如果是null,直接返回true;如果是類數組,判斷數據長度;如果是Object對象,判斷是否具有屬性;如果是其他數據,直接返回false(也可改為返回true)

function isEmpty(value) {  if (value == null) {    return true;  }  if (isArrayLike(value)) {    return !value.length;  }else if(isPlainObject(value)){     for (let key in value) {      if (hasOwnProperty.call(value, key)) {       return false;      }    }    return true;  }  return false;}

15、cached:記憶函數:緩存函數的運算結果

function cached(fn) {  let cache = Object.create(null);  return function cachedFn(str) {    let hit = cache[str];    return hit || (cache[str] = fn(str))  }}

16、camelize:橫線轉駝峰命名

let camelizeRE = /-(/w)/g;function camelize(str) {  return str.replace(camelizeRE, function(_, c) {    return c ? c.toUpperCase() : '';  })}//ab-cd-ef ==> abCdEf//使用記憶函數let _camelize = cached(camelize)

17、hyphenate:駝峰命名轉橫線命名:拆分字符串,使用 - 相連,并且轉換為小寫

let hyphenateRE = //B([A-Z])/g;function hyphenate(str){  return str.replace(hyphenateRE, '-$1').toLowerCase()}//abCd ==> ab-cd//使用記憶函數let _hyphenate = cached(hyphenate);

18、capitalize:字符串首位大寫

function capitalize(str){  return str.charAt(0).toUpperCase() + str.slice(1)}// abc ==> Abc//使用記憶函數let _capitalize = cached(capitalize)

19、extend:將屬性混合到目標對象中

function extend(to, _from) {  for(let key in _from) {    to[key] = _from[key];  }  return to}

20、Object.assign:對象屬性復制,淺拷貝

Object.assign = Object.assign || function(){  if(arguments.length == 0) throw new TypeError('Cannot convert undefined or null to object');    let target = arguments[0],    args = Array.prototype.slice.call(arguments, 1),    key  args.forEach(function(item){    for(key in item){      item.hasOwnProperty(key) && ( target[key] = item[key] )    }  })  return target}

使用Object.assign可以淺克隆一個對象:

let clone = Object.assign({}, target)

簡單的深克隆可以使用JSON.parse()和JSON.stringify(),這兩個api是解析json數據的,所以只能解析除symbol外的原始類型及數組和對象

let clone = JSON.parse( JSON.stringify(target) )

21、clone:克隆數據,可深度克隆

這里列出了原始類型,時間、正則、錯誤、數組、對象的克隆規則,其他的可自行補充

function clone(value, deep){  if(isPrimitive(value)){    return value  }    if (isArrayLike(value)) { //是類數組    value = Array.prototype.slice.call(value)    return value.map(item => deep ? clone(item, deep) : item)    }else if(isPlainObject(value)){ //是對象      let target = {}, key;     for (key in value) {      value.hasOwnProperty(key) && ( target[key] = deep ? clone(value[key], deep) : value[key] )    }  }    let type = getRawType(value)    switch(type){    case 'Date':    case 'RegExp':     case 'Error': value = new window[type](value); break;  }  return value}

22、識別各種瀏覽器及平臺

//運行環境是瀏覽器let inBrowser = typeof window !== 'undefined';//運行環境是微信let inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform;let weexPlatform = inWeex && WXEnvironment.platform.toLowerCase();//瀏覽器 UA 判斷let UA = inBrowser && window.navigator.userAgent.toLowerCase();let isIE = UA && /msie|trident/.test(UA);let isIE9 = UA && UA.indexOf('msie 9.0') > 0;let isEdge = UA && UA.indexOf('edge/') > 0;let isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android');let isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios');let isChrome = UA && /chrome///d+/.test(UA) && !isEdge;

23、getExplorerInfo:獲取瀏覽器信息

function getExplorerInfo() {  let t = navigator.userAgent.toLowerCase();  return 0 <= t.indexOf("msie") ? { //ie < 11    type: "IE",    version: Number(t.match(/msie ([/d]+)/)[1])  } : !!t.match(/trident//.+?rv:(([/d.]+))/) ? { // ie 11    type: "IE",    version: 11  } : 0 <= t.indexOf("edge") ? {    type: "Edge",    version: Number(t.match(/edge//([/d]+)/)[1])  } : 0 <= t.indexOf("firefox") ? {    type: "Firefox",    version: Number(t.match(/firefox//([/d]+)/)[1])  } : 0 <= t.indexOf("chrome") ? {    type: "Chrome",    version: Number(t.match(/chrome//([/d]+)/)[1])  } : 0 <= t.indexOf("opera") ? {    type: "Opera",    version: Number(t.match(/opera.([/d]+)/)[1])  } : 0 <= t.indexOf("Safari") ? {    type: "Safari",    version: Number(t.match(/version//([/d]+)/)[1])  } : {    type: t,    version: -1  }}

24、isPCBroswer:檢測是否為PC端瀏覽器模式

function isPCBroswer() {  let e = navigator.userAgent.toLowerCase()    , t = "ipad" == e.match(/ipad/i)    , i = "iphone" == e.match(/iphone/i)    , r = "midp" == e.match(/midp/i)    , n = "rv:1.2.3.4" == e.match(/rv:1.2.3.4/i)    , a = "ucweb" == e.match(/ucweb/i)    , o = "android" == e.match(/android/i)    , s = "windows ce" == e.match(/windows ce/i)    , l = "windows mobile" == e.match(/windows mobile/i);  return !(t || i || r || n || a || o || s || l)}

25、unique:數組去重,返回一個新數組

function unique(arr){  if(!isArrayLink(arr)){ //不是類數組對象    return arr  }  let result = []  let objarr = []  let obj = Object.create(null)    arr.forEach(item => {    if(isStatic(item)){//是除了symbol外的原始數據      let key = item + '_' + getRawType(item);      if(!obj[key]){        obj[key] = true        result.push(item)      }    }else{//引用類型及symbol      if(!objarr.includes(item)){        objarr.push(item)        result.push(item)      }    }  })    return resulte}

26、Set簡單實現

window.Set = window.Set || (function () {  function Set(arr) {    this.items = arr ? unique(arr) : [];    this.size = this.items.length; // Array的大小  }  Set.prototype = {    add: function (value) {      // 添加元素,若元素已存在,則跳過,返回 Set 結構本身。      if (!this.has(value)) {        this.items.push(value);        this.size++;      }      return this;    },    clear: function () {      //清除所有成員,沒有返回值。      this.items = []      this.size = 0    },    delete: function (value) {      //刪除某個值,返回一個布爾值,表示刪除是否成功。      return this.items.some((v, i) => {        if(v === value){          this.items.splice(i,1)          return true        }        return false      })    },    has: function (value) {      //返回一個布爾值,表示該值是否為Set的成員。      return this.items.some(v => v === value)    },    values: function () {      return this.items    },  }  return Set;}());

27、repeat:生成一個重復的字符串,有n個str組成,可修改為填充為數組等

function repeat(str, n) {  let res = '';  while(n) {    if(n % 2 === 1) {      res += str;    }    if(n > 1) {      str += str;    }    n >>= 1;  }  return res};//repeat('123',3) ==> 123123123

28、dateFormater:格式化時間

function dateFormater(formater, t){  let date = t ? new Date(t) : new Date(),    Y = date.getFullYear() + '',    M = date.getMonth() + 1,    D = date.getDate(),    H = date.getHours(),    m = date.getMinutes(),    s = date.getSeconds();  return formater.replace(/YYYY|yyyy/g,Y)    .replace(/YY|yy/g,Y.substr(2,2))    .replace(/MM/g,(M<10?'0':'') + M)    .replace(/DD/g,(D<10?'0':'') + D)    .replace(/HH|hh/g,(H<10?'0':'') + H)    .replace(/mm/g,(m<10?'0':'') + m)    .replace(/ss/g,(s<10?'0':'') + s)}// dateFormater('YYYY-MM-DD HH:mm', t) ==> 2019-06-26 18:30// dateFormater('YYYYMMDDHHmm', t) ==> 201906261830

29、dateStrForma:將指定字符串由一種時間格式轉化為另一種

from的格式應對應str的位置

function dateStrForma(str, from, to){  //'20190626' 'YYYYMMDD' 'YYYY年MM月DD日'  str += ''  let Y = ''  if(~(Y = from.indexOf('YYYY'))){    Y = str.substr(Y, 4)    to = to.replace(/YYYY|yyyy/g,Y)  }else if(~(Y = from.indexOf('YY'))){    Y = str.substr(Y, 2)    to = to.replace(/YY|yy/g,Y)  }  let k,i  ['M','D','H','h','m','s'].forEach(s =>{    i = from.indexOf(s+s)    k = ~i ? str.substr(i, 2) : ''    to = to.replace(s+s, k)  })  return to}// dateStrForma('20190626', 'YYYYMMDD', 'YYYY年MM月DD日') ==> 2019年06月26日// dateStrForma('121220190626', '----YYYYMMDD', 'YYYY年MM月DD日') ==> 2019年06月26日// dateStrForma('2019年06月26日', 'YYYY年MM月DD日', 'YYYYMMDD') ==> 20190626// 一般的也可以使用正則來實現//'2019年06月26日'.replace(/(/d{4})年(/d{2})月(/d{2})日/, '$1-$2-$3') ==> 2019-06-26

30、getPropByPath:根據字符串路徑獲取對象屬性 : 'obj[0].count'

function getPropByPath(obj, path, strict) {   let tempObj = obj;   path = path.replace(//[(/w+)/]/g, '.$1'); //將[0]轉化為.0   path = path.replace(/^/./, ''); //去除開頭的.   let keyArr = path.split('.'); //根據.切割   let i = 0;   for (let len = keyArr.length; i < len - 1; ++i) {    if (!tempObj && !strict) break;    let key = keyArr[i];    if (key in tempObj) {      tempObj = tempObj[key];    } else {      if (strict) {//開啟嚴格模式,沒找到對應key值,拋出錯誤        throw new Error('please transfer a valid prop path to form item!');      }      break;    }   }   return {    o: tempObj, //原始數據    k: keyArr[i], //key值    v: tempObj ? tempObj[keyArr[i]] : null // key值對應的值   };};

31、GetUrlParam:獲取Url參數,返回一個對象

function GetUrlParam(){  let url = document.location.toString();  let arrObj = url.split("?");  let params = Object.create(null)  if (arrObj.length > 1){    arrObj = arrObj[1].split("&");    arrObj.forEach(item=>{      item = item.split("=");      params[item[0]] = item[1]    })  }  return params;}// ?a=1&b=2&c=3 ==> {a: "1", b: "2", c: "3"}

32、downloadFile:base64數據導出文件,文件下載

function downloadFile(filename, data){  let DownloadLink = document.createElement('a');  if ( DownloadLink ){    document.body.appendChild(DownloadLink);    DownloadLink.style = 'display: none';    DownloadLink.download = filename;    DownloadLink.href = data;    if ( document.createEvent ){      let DownloadEvt = document.createEvent('MouseEvents');      DownloadEvt.initEvent('click', true, false);      DownloadLink.dispatchEvent(DownloadEvt);    }    else if ( document.createEventObject )      DownloadLink.fireEvent('onclick');    else if (typeof DownloadLink.onclick == 'function' )      DownloadLink.onclick();    document.body.removeChild(DownloadLink);  }}

33、toFullScreen:全屏

function toFullScreen(){  let elem = document.body;  elem.webkitRequestFullScreen   ? elem.webkitRequestFullScreen()  : elem.mozRequestFullScreen  ? elem.mozRequestFullScreen()  : elem.msRequestFullscreen  ? elem.msRequestFullscreen()  : elem.requestFullScreen  ? elem.requestFullScreen()  : alert("瀏覽器不支持全屏");}

34、exitFullscreen:退出全屏

function exitFullscreen(){  let elem = parent.document;  elem.webkitCancelFullScreen   ? elem.webkitCancelFullScreen()  : elem.mozCancelFullScreen  ? elem.mozCancelFullScreen()  : elem.cancelFullScreen  ? elem.cancelFullScreen()  : elem.msExitFullscreen  ? elem.msExitFullscreen()  : elem.exitFullscreen  ? elem.exitFullscreen()  : alert("切換失敗,可嘗試Esc退出");}

35、requestAnimationFrame:window動畫

window.requestAnimationFrame = window.requestAnimationFrame ||  window.webkitRequestAnimationFrame ||  window.mozRequestAnimationFrame ||  window.msRequestAnimationFrame ||  window.oRequestAnimationFrame ||  function (callback) {    //為了使setTimteout的盡可能的接近每秒60幀的效果    window.setTimeout(callback, 1000 / 60);  };  window.cancelAnimationFrame = window.cancelAnimationFrame ||  Window.webkitCancelAnimationFrame ||  window.mozCancelAnimationFrame ||  window.msCancelAnimationFrame ||  window.oCancelAnimationFrame ||  function (id) {    //為了使setTimteout的盡可能的接近每秒60幀的效果    window.clearTimeout(id);  }

36、_isNaN:檢查數據是否是非數字值

原生的isNaN會把參數轉換成數字(valueof),而null、true、false以及長度小于等于1的數組(元素為非NaN數據)會被轉換成數字,這不是我想要的。Symbol類型的數據不具有valueof接口,所以isNaN會拋出錯誤,這里放在后面,可避免錯誤

function _isNaN(v){  return !(typeof v === 'string' || typeof v === 'number') || isNaN(v)}

37、max:求取數組中非NaN數據中的最大值

function max(arr){  arr = arr.filter(item => !_isNaN(item))  return arr.length ? Math.max.apply(null, arr) : undefined}//max([1, 2, '11', null, 'fdf', []]) ==> 11

38、min:求取數組中非NaN數據中的最小值

function min(arr){  arr = arr.filter(item => !_isNaN(item))  return arr.length ? Math.min.apply(null, arr) : undefined}//min([1, 2, '11', null, 'fdf', []]) ==> 1

39、random:返回一個lower - upper之間的隨機數

lower、upper無論正負與大小,但必須是非NaN的數據

function random(lower, upper){  lower = +lower || 0  upper = +upper || 0  return Math.random() * (upper - lower) + lower;}//random(0, 0.5) ==> 0.3567039135734613//random(2, 1) ===> 1.6718418553475423//random(-2, -1) ==> -1.4474325452361945

40、Object.keys:返回一個由一個給定對象的自身可枚舉屬性組成的數組

Object.keys = Object.keys || function keys(object) {  if(object === null || object === undefined){    throw new TypeError('Cannot convert undefined or null to object');  }  let result = []  if(isArrayLike(object) || isPlainObject(object)){    for (let key in object) {      object.hasOwnProperty(key) && ( result.push(key) )    }  }  return result}

41、Object.values:返回一個給定對象自身的所有可枚舉屬性值的數組

Object.values = Object.values || function values(object) {  if(object === null || object === undefined){    throw new TypeError('Cannot convert undefined or null to object');  }  let result = []  if(isArrayLike(object) || isPlainObject(object)){    for (let key in object) {      object.hasOwnProperty(key) && ( result.push(object[key]) )    }  }  return result}

42、arr.fill:使用 value 值來填充 array,從start位置開始, 到end位置結束(但不包含end位置),返回原數組

Array.prototype.fill = Array.prototype.fill || function fill(value, start, end) {  let ctx = this  let length = ctx.length;    start = parseInt(start)  if(isNaN(start)){    start = 0  }else if (start < 0) {    start = -start > length ? 0 : (length + start);   }      end = parseInt(end)   if(isNaN(end) || end > length){     end = length   }else if (end < 0) {    end += length;  }    while (start < end) {    ctx[start++] = value;  }  return ctx;}//Array(3).fill(2) ===> [2, 2, 2]

43、arr.includes:用來判斷一個數組是否包含一個指定的值,如果是返回 true,否則false,可指定開始查詢的位置

Array.prototype.includes = Array.prototype.includes || function includes(value, start){  let ctx = this  let length = ctx.length;    start = parseInt(start)  if(isNaN(start)){    start = 0  }else if (start < 0) {    start = -start > length ? 0 : (length + start);   }    let index = ctx.indexOf(value)    return index >= start;}

44、arr.find:返回數組中通過測試(函數fn內判斷)的第一個元素的值

Array.prototype.find = Array.prototype.find || function find(fn, ctx){  fn = fn.bind(ctx)    let result;  this.some((value, index, arr), thisValue) => {    return fn(value, index, arr) ? (result = value, true) : false  })    return result}

45、arr.findIndex :返回數組中通過測試(函數fn內判斷)的第一個元素的下標

Array.prototype.findIndex = Array.prototype.findIndex || function findIndex(fn, ctx){  fn = fn.bind(ctx)    let result;  this.some((value, index, arr), thisValue) => {    return fn(value, index, arr) ? (result = index, true) : false  })    return result}

46、performance.timing:利用performance.timing進行性能分析

window.onload = function(){  setTimeout(function(){    let t = performance.timing    console.log('DNS查詢耗時 :' + (t.domainLookupEnd - t.domainLookupStart).toFixed(0))    console.log('TCP鏈接耗時 :' + (t.connectEnd - t.connectStart).toFixed(0))    console.log('request請求耗時 :' + (t.responseEnd - t.responseStart).toFixed(0))    console.log('解析dom樹耗時 :' + (t.domComplete - t.domInteractive).toFixed(0))    console.log('白屏時間 :' + (t.responseStart - t.navigationStart).toFixed(0))    console.log('domready時間 :' + (t.domContentLoadedEventEnd - t.navigationStart).toFixed(0))    console.log('onload時間 :' + (t.loadEventEnd - t.navigationStart).toFixed(0))    if(t = performance.memory){      console.log('js內存使用占比 :' + (t.usedJSHeapSize / t.totalJSHeapSize * 100).toFixed(2) + '%')    }  })}

47、禁止某些鍵盤事件

document.addEventListener('keydown', function(event){  return !(    112 == event.keyCode || //F1    123 == event.keyCode || //F12    event.ctrlKey && 82 == event.keyCode || //ctrl + R    event.ctrlKey && 78 == event.keyCode || //ctrl + N    event.shiftKey && 121 == event.keyCode || //shift + F10    event.altKey && 115 == event.keyCode || //alt + F4    "A" == event.srcElement.tagName && event.shiftKey //shift + 點擊a標簽  ) || (event.returnValue = false)});

48、禁止右鍵、選擇、復制

['contextmenu', 'selectstart', 'copy'].forEach(function(ev){  document.addEventListener(ev, function(event){    return event.returnValue = false  })});

github地址:https://github.com/hfhan/tools

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日本国产在线| 亚洲一区美女视频在线观看免费| 国产精品999999| 亚洲亚裔videos黑人hd| 亚洲欧美日本精品| 欧美成人一区二区三区电影| 欧美高清在线视频观看不卡| 日日骚av一区| 在线视频免费一区二区| 国产精品青青在线观看爽香蕉| 91国产中文字幕| 国产一区二区三区欧美| 日韩在线观看免费高清完整版| 中文字幕在线看视频国产欧美在线看完整| 国产精品久久久久久久久久ktv| 国产精品自拍偷拍| 亚洲天堂第一页| 欧美日韩成人网| 久久国产天堂福利天堂| 日韩成人在线电影网| 国产精品爽黄69天堂a| 亚洲女成人图区| www.欧美三级电影.com| 欧美电影在线免费观看网站| 亚洲人av在线影院| 亚洲福利在线视频| 韩国三级电影久久久久久| 欧美做受高潮电影o| 国产精品观看在线亚洲人成网| 国产精品美女www爽爽爽视频| 中文字幕免费国产精品| 亚洲xxx大片| 欧美极品少妇全裸体| 国产精品视频男人的天堂| 国产精品久久婷婷六月丁香| 国产精品欧美在线| 日本中文字幕成人| 欧美福利在线观看| 国产精品高潮呻吟久久av无限| 国产精品视频男人的天堂| 国产深夜精品福利| 91av在线影院| 国产噜噜噜噜久久久久久久久| 久久久之久亚州精品露出| 国产suv精品一区二区三区88区| 中文字幕欧美亚洲| 国产69精品久久久久久| 亚洲网站在线观看| 国产97在线视频| 欧美人与性动交a欧美精品| 国产视频福利一区| 日韩在线观看高清| 国产精品色悠悠| 黄色成人在线播放| 国产精品一久久香蕉国产线看观看| 亚洲综合日韩中文字幕v在线| 91精品国产九九九久久久亚洲| 国产91色在线| 中文字幕一精品亚洲无线一区| 91精品久久久久久综合乱菊| 国产精品久久久久久五月尺| 国产欧美久久久久久| 欧美日韩成人在线视频| 国产成人精品在线观看| 国产精品自拍视频| 日韩激情视频在线| 国产成人精品久久二区二区91| 亚洲**2019国产| 亚洲精品视频免费| 97精品一区二区三区| 久久久久久久久久久人体| 久久久精品欧美| 美女扒开尿口让男人操亚洲视频网站| 久久九九热免费视频| 亚洲女人天堂视频| 日韩欧美在线中文字幕| 中文字幕亚洲无线码在线一区| 一区二区中文字幕| 国产精品一区二区三区久久久| 国外色69视频在线观看| 伊人久久五月天| 亚洲第一区在线观看| 国产精品流白浆视频| 国产综合色香蕉精品| 国产精品视频久| 国产精品久久久久久久7电影| 91影院在线免费观看视频| 亚洲永久免费观看| 九色91av视频| 92福利视频午夜1000合集在线观看| 国产精品久久久av久久久| 久久精品国产亚洲7777| 日韩高清av一区二区三区| 国产精品久久国产精品99gif| 久久精品色欧美aⅴ一区二区| 久久久成人精品| 亚洲天堂开心观看| 日韩电影中文字幕一区| 亚洲xxxx在线| 亚洲影院色无极综合| 国产成人+综合亚洲+天堂| 亚洲自拍偷拍区| 亚洲欧洲视频在线| 在线免费观看羞羞视频一区二区| 久久九九国产精品怡红院| 欧美成人精品三级在线观看| 国产精品一区二区三| 97色在线观看免费视频| 欧美在线观看一区二区三区| 国产精品自拍网| 亚洲免费电影在线观看| 欧美成人精品激情在线观看| 91在线网站视频| 国产日韩av在线播放| 欧美伊久线香蕉线新在线| 国产欧美va欧美va香蕉在| 日韩电影在线观看永久视频免费网站| 久久国产精品久久久久| 一区二区三区亚洲| 国产91精品久| 色综合久久中文字幕综合网小说| 久久久久久久久国产精品| 国产日韩换脸av一区在线观看| 亚洲国产精品久久久久| 日韩av在线影院| 欧美电影免费播放| 亚洲无限av看| 亚洲色图偷窥自拍| 久久精品国产欧美激情| xxx成人少妇69| 亚洲成人av片在线观看| 欧美国产高跟鞋裸体秀xxxhd| 亚洲精品欧美一区二区三区| 亚洲精品久久久久久下一站| 国产精品欧美在线| 久久精品国产亚洲精品2020| 久久久精品国产亚洲| 久久97久久97精品免视看| 亚洲天堂色网站| 欧美日韩在线一区| 亚洲国产精品久久91精品| 日韩视频亚洲视频| 色系列之999| 国产精彩精品视频| 久久久久久成人精品| 成人做爽爽免费视频| 欧美视频国产精品| 狠狠色狠狠色综合日日五| 成人久久久久爱| 国产精品美乳一区二区免费| 欧洲美女免费图片一区| 色哟哟亚洲精品一区二区| 久久天天躁狠狠躁夜夜av| 国产日韩在线看| www国产精品视频| 国产丝袜一区二区三区免费视频| 亚洲男人的天堂在线| 国产精品入口尤物| 91精品久久久久| 久久久噜噜噜久久| 精品成人在线视频| 午夜免费久久久久| 亚洲精品久久久一区二区三区| 国产精品老女人视频|