10個非常實用的工具函數

生成一周時間

new Array 創建的數組只是添加了length屬性,並沒有實際的內容。通過擴展後,變為可用數組用於循環

function getWeekTime(){    return [...new Array(7)].map((j,i)=> new Date(Date.now()+i*8.64e7).toLocaleDateString())  }

使用

getWeekTime()  // ["2020/2/26", "2020/2/27", "2020/2/28", "2020/2/29", "2020/3/1", "2020/3/2", "2020/3/3"]

類型判斷

判斷核心使用Object.prototype.toString,這種方式可以準確的判斷數據類型。

/**   * @param {any} target   * @param {string} type   * @return {boolean}   */  function isType(target, type) {    let targetType = Object.prototype.toString.call(target).slice(8, -1).toLowerCase()    return targetType === type.toLowerCase()  }

使用

isType([], 'Array') // true  isType(/d/, 'RegExp') // true  isType(new Date(), 'Date') // true  isType(function(){}, 'Function') // true  isType(Symbol(1), 'Symbol') // true

對象屬性剔除

應用場景很簡單,當你需要使用一個對象,但想移除部分屬性時,可以使用該方法。同樣的,你可以實現一個對象屬性選取方法。

/**   * @param {object} object   * @param {string[]} props   * @return {object}   */  function omit(object, props=[]){    let res = {}    Object.keys(object).forEach(key=>{      if(props.includes(key) === false){        res[key] = typeof object[key] === 'object' && object[key] !== null ?          JSON.parse(JSON.stringify(object[key])):          object[key]      }    })    return res  }

使用

let data = {    id: 1,    title: 'xxx',    comment: []  }  omit(data, ['id']) // {title: 'xxx', comment: []}

日期格式化

一個很靈活的日期格式化函數,可以根據使用者給定的格式進行格式化,能應對大部分場景

/**   * @param {string} format   * @param {number} timestamp - 時間戳   * @return {string}   */  function formatDate(format='Y-M-D h:m', timestamp=Date.now()){    let date = new Date(timestamp)    let dateInfo = {      Y: date.getFullYear(),      M: date.getMonth()+1,      D: date.getDate(),      h: date.getHours(),      m: date.getMinutes(),      s: date.getSeconds()    }    let formatNumber = (n) => n > 10 ? n : '0' + n    let res = format      .replace('Y', dateInfo.Y)      .replace('M', dateInfo.M)      .replace('D', dateInfo.D)      .replace('h', formatNumber(dateInfo.h))      .replace('m', formatNumber(dateInfo.m))      .replace('s', formatNumber(dateInfo.s))    return res  }

使用

formatDate() // "2020-2-24 13:44"  formatDate('M月D日 h:m') // "2月24日 13:45"  formatDate('h:m Y-M-D', 1582526221604) // "14:37 2020-2-24"

性能分析

Web Performance API允許網頁訪問某些函數來測量網頁和Web應用程序的性能

performance.timing 包含延遲相關的性能信息

performance.memory 包含內存信息,是Chrome中添加的一個非標準擴展,在使用時需要注意

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

防抖

性能優化方案,防抖用於減少函數請求次數,對於頻繁的請求,只執行這些請求的最後一次。

基礎版本

function debounce(func, wait = 300){    let timer = null;    return function(){      if(timer !== null){        clearTimeout(timer);      }      timer = setTimeout(fn,wait);    }  }

改進版本添加是否立即執行的參數,因為有些場景下,我們希望函數能立即執行。

/**   * @param {function} func - 執行函數   * @param {number} wait - 等待時間   * @param {boolean} immediate - 是否立即執行   * @return {function}   */  function debounce(func, wait = 300, immediate = false){    let timer, ctx;    let later = (arg) => setTimeout(()=>{      func.apply(ctx, arg)      timer = ctx = null    }, wait)    return function(...arg){      if(!timer){        timer = later(arg)        ctx = this        if(immediate){          func.apply(ctx, arg)        }      }else{        clearTimeout(timer)        timer = later(arg)      }    }  }

使用

let scrollHandler = debounce(function(e){    console.log(e)  }, 500)  window.onscroll = scrollHandler

節流

性能優化方案,節流用於減少函數請求次數,與防抖不同,節流是在一段時間執行一次。

/**   * @param {function} func - 執行函數   * @param {number} delay - 延遲時間   * @return {function}   */  function throttle(func, delay){    let timer = null    return function(...arg){      if(!timer){        timer = setTimeout(()=>{          func.apply(this, arg)          timer = null        }, delay)      }    }  }

使用

let scrollHandler = throttle(function(e){    console.log(e)  }, 500)  window.onscroll = scrollHandler

base64數據導出文件下載

/**   * @param {string} filename - 下載時的文件名   * @param {string} data - 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);    }  } 

檢測是否為PC端瀏覽器

function isPCBroswer() {    let e = window.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)  } 

識別瀏覽器及平台

function getPlatformInfo(){    //運行環境是瀏覽器    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();    if(UA){      let platforms = {        IE: /msie|trident/.test(UA),        IE9: UA.indexOf('msie 9.0') > 0,        Edge: UA.indexOf('edge/') > 0,        Android: UA.indexOf('android') > 0 || (weexPlatform === 'android'),        IOS: /iphone|ipad|ipod|ios/.test(UA) || (weexPlatform === 'ios'),        Chrome: /chrome/d+/.test(UA) && !(UA.indexOf('edge/') > 0),      }      for (const key in platforms) {        if (platforms.hasOwnProperty(key)) {          if(platforms[key]) return key        }      }    }  }