一些高频使用的JavaScript方法封装(持续更新)

171 阅读1分钟

1.空对象判断

function isEmptyObj(obj){
  if (Object.prototype.toString.call(obj) !== '[object Object]') {
    return true
  } else if (!Object.keys(obj).length) {
    return true
  } else {
    return false
  }
}

2.数组去重

function unique1(arr) {
    return [...new Set(arr)]
}

function unique2(arr) {
  var obj = {}
  return arr.filter(item => {
    if (!obj[item]) {
        obj[item] = true
        return true
    }
  })
}

function unique3(arr) {
  var result = []
  arr.forEach(item => {
    if (result.indexOf(item) == -1) {
      result.push(item)
    }
  })
  return result
}

3.字符串去重

String.prototype.unique = function () {
  var obj = {},
      str = '',
      len = this.length
  for (var i = 0; i < len; i++) {
    if (!obj[this[i]]) {
      str += this[i]
      obj[this[i]] = true
    }
  }
  return str
}

//去除连续的字符串 
function uniq(str) {
    return str.replace(/(\w)\1+/g, '$1')
}

4.深拷贝 浅拷贝

//深拷贝(深拷贝不考虑函数)
function deepClone(obj, result) {
  var result = result || {}
  for (var prop in obj) {
    if (obj.hasOwnProperty(prop)) {
      if (typeof obj[prop] == 'object' && obj[prop] !== null) {
        // 引用值(obj/array)且不为null
        if (Object.prototype.toString.call(obj[prop]) == '[object Object]') {
          // 对象
          result[prop] = {};
        } else {
          // 数组
          result[prop] = [];
        }
        deepClone(obj[prop], result[prop])
      } else {
        // 原始值或func
        result[prop] = obj[prop]
      }
    }
  }
  return result
}

// 深浅拷贝是针对引用值
function deepClone(target) {
  if (typeof (target) !== 'object') {
    return target;
  }
  var result;
  if (Object.prototype.toString.call(target) == '[object Array]') {
    // 数组
    result = []
  } else {
    // 对象
    result = {};
  }
  for (var prop in target) {
    if (target.hasOwnProperty(prop)) {
      result[prop] = deepClone(target[prop])
    }
  }
  return result;
}
// 无法复制函数
var o1 = jsON.parse(jsON.stringify(obj1));

5.reverse底层原理和扩展

// 改变原数组
Array.prototype.myReverse = function () {
  var len = this.length
  for (var i = 0; i < len; i++) {
    var temp = this[i]
    this[i] = this[len - 1 - i]
    this[len - 1 - i] = temp
  }
  return this
}

6.圣杯模式的继承

function inherit(Target, Origin) {
  function F() {};
  F.prototype = Origin.prototype
  Target.prototype = new F()
  Target.prototype.constructor = Target
  // 最终的原型指向
  Target.prop.uber = Origin.prototype
}

7.找出字符串中第一次只出现一次的字母

String.prototype.firstAppear = function () {
  var obj = {},
      len = this.length
  for (var i = 0; i < len; i++) {
    if (obj[this[i]]) {
      obj[this[i]]++
    } else {
      obj[this[i]] = 1
    }
  }
  for (var prop in obj) {
    if (obj[prop] == 1) {
    return prop
    }
  }
}

8.找元素的第n级父元素

function parents(el, n) {
  while (el && n) {
    el = el.parentElement ? el.parentElement : el.parentNode
    n--
  }
  return el
}

9.返回元素的第n个兄弟节点

function retSibling(e, n) {
  while (e && n) {
    if (n > 0) {
      if (e.nextElementSibling) {
        e = e.nextElementSibling
      } else {
        for (e = e.nextSibling; e && e.nodeType !== 1; e = e.nextSibling)
      }
      n--
    } else {
      if (e.previousElementSibling) {
        e = e.previousElementSibling
      } else {
        for (e = e.previousElementSibling; e && e.nodeType !== 1; e = e.previousElementSibling)
      }
      n++
    }
  }
  return e
}

10.封装mychildren,解决浏览器的兼容问题

function myChildren(e) {
  var children = e.childNodes,
    arr = [],
    len = children.length
  for (var i = 0; i < len; i++) {
    if (children[i].nodeType === 1) {
      arr.push(children[i])
    }
  }
  return arr
}

11.判断元素有没有子元素

function hasChildren(e) {
  var children = e.childNodes,
      len = children.length
  for (var i = 0; i < len; i++) {
    if (children[i].nodeType === 1) {
      return true
    }
  }
  return false
}

12.我一个元素插入到另一个元素的后面

Element.prototype.insertAfter = function (target, elen) {
  var nextElen = elen.nextElenmentSibling
  if (nextElen == null) {
    this.appendChild(target)
  } else {
    this.insertBefore(target, nextElen)
  }
}

13.返回当前的时间(年月日时分秒)

function getDateTime() {
  var date = new Date(),
      year = date.getFullYear(),
      month = date.getMonth() + 1,
      day = date.getDate(),
      hour = date.getHours() + 1,
      minute = date.getMinutes()
      second = date.getSeconds()
  month = checkTime(month)
  day = checkTime(day)
  hour = checkTime(hour)
  minute = checkTime(minute)
  second = checkTime(second)
  function checkTime(i) {
    if (i < 10) {
      i = "0" + i
    }
    return i
  }
  return "" + year + "年" + month + "月" + day + "日" + hour + "时" + minute + "分" + second + "秒"
}

14.获得滚动条的滚动距离

function getScrollOffset() {
  if (window.pageXOffset) {
    return {
      x: window.pageXOffset,
      y: window.pageYOffset
    }
  } else {
    return {
      x: document.body.scrollLeft + document.documentElement.scrollLeft,
      y: document.body.scrollTop + document.documentElement.scrollTop
    }
  }
}

15.获得视口的尺寸

function getViewportOffset() {
  if (window.innerWidth) {
    return {
      w: window.innerWidth,
      h: window.innerHeight
    }
  } else {
    // ie8及其以下
    if (document.compatMode === "BackCompat") {
      // 怪异模式
      return {
        w: document.body.clientWidth,
        h: document.body.clientHeight
      }
    } else {
      // 标准模式
      return {
        w: document.documentElement.clientWidth,
        h: document.documentElement.clientHeight
      }
    }
  }
}

16.获取任一元素的任意属性

function getStyle(el, prop) {
  return window.getComputedStyle ? window.getComputedStyle(el, null)[prop] : el.currentStyle[prop]
}

17.绑定事件的兼容代码

function addEvent(el, type, handle) {
  if (el.addEventListener) { //非ie和非ie9
    el.addEventListener(type, handle, false);
  } else if (el.attachEvent) { //ie6到ie8
    el.attachEvent('on' + type, function () {
      handle.call(el)
    })
  } else {
    el['on' + type] = handle
  }
}

18.解绑事件

function removeEvent(el, type, handle) {
  if (el.removeEventListener) { //非ie和非ie9
    el.removeEventListener(type, handle, false)
  } else if (el.detachEvent) { //ie6到ie8
    el.detachEvent('on' + type, handle)
  } else {
    el['on' + type] = null
  }
}

19.取消冒泡的兼容代码

function stopBubble(e) {
  if (e && e.stopPropagation) {
    e.stopPropagation()
  } else {
    window.event.cancelBubble = true
  }
}

20.封装自己的forEach方法

Array.prototype.myForEach = function (func, obj) {
  var len = this.length
  var _this = arguments[1] ? arguments[1] : window
  for (var i = 0; i < len; i++) {
    func.call(_this, this[i], i, this)
  }
}

21.封装自己的filter方法

Array.prototype.myFilter = function (func, obj) {
  var len = this.length
  var arr = []
  var _this = arguments[1] || window
  for (var i = 0; i < len; i++) {
    func.call(_this, this[i], i, this) && arr.push(this[i])
  }
  return arr
}

22.数组map方法

Array.prototype.myMap = function (func) {
  var arr = []
  var len = this.length
  var _this = arguments[1] || window
  for (var i = 0; i < len; i++) {
    arr.push(func.call(_this, this[i], i, this))
  }
  return arr
}

23.数组every方法

Array.prototype.myEvery = function (func) {
  var flag = true
  var len = this.length
  var _this = arguments[1] || window
  for (var i = 0; i < len; i++) {
    if (func.apply(_this, [this[i], i, this]) == false) {
      flag = false
      break
    }
  }
  return flag
}

24.数组reduce方法

Array.prototype.myReduce = function (func, initialValue) {
  var len = this.length,
      nextValue,
      i
  if (!initialValue) {
    // 没有传第二个参数
    nextValue = this[0]
    i = 1
  } else {
    // 传了第二个参数
    nextValue = initialValue
    i = 0
  }
  for (; i < len; i++) {
    nextValue = func(nextValue, this[i], i, this)
  }
  return nextValue
}

25.获取url中的参数

function getWindonHref() {
  var sHref = window.location.href
  var args = sHref.split('?')
  if (args[0] === sHref) {
    return ''
  }
  var hrefarr = args[1].split('#')[0].split('&')
  var obj = {}
  for (var i = 0; i < hrefarr.length; i++) {
    hrefarr[i] = hrefarr[i].split('=')
    obj[hrefarr[i][0]] = hrefarr[i][1]
  }
  return obj
}

26.数组排序

// 快排
function quickArr(arr) {
  if (arr.length <= 1) {
    return arr
  }
  var left = [],
      right = []
  var pIndex = Math.floor(arr.length / 2)
  var p = arr.splice(pIndex, 1)[0]
  for (var i = 0; i < arr.length; i++) {
    if (arr[i] <= p) {
      left.push(arr[i])
    } else {
      right.push(arr[i])
    }
  }
  // 递归
  return quickArr(left).concat([p], quickArr(right));
}

// 冒泡
function bubbleSort(arr) {
  for (var i = 0; i < arr.length - 1; i++) {
    for (var j = i + 1; j < arr.length; j++) {
      if (arr[i] > arr[j]) {
        var temp = arr[i]
        arr[i] = arr[j]
        arr[j] = temp
      }
    }
  }
  return arr
}

function bubbleSort(arr) {
  var len = arr.length;
  for (var i = 0; i < len - 1; i++) {
    for (var j = 0; j < len - 1 - i; j++) {
      if (arr[j] > arr[j + 1]) {
        var temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
      }
    }
  }
  return arr;
}

27.遍历Dom树

// 给定页面上的DOM元素,将访问元素本身及其所有后代(不仅仅是它的直接子元素)
// 对于每个访问的元素,函数讲元素传递给提供的回调函数
function traverse(element, callback) {
  callback(element)
  var list = element.children
  for (var i = 0; i < list.length; i++) {
    traverse(list[i], callback)
  }
}

28.原生js封装ajax

function ajax(method, url, callback, data, flag) {
  var xhr
  flag = flag || true
  method = method.toUpperCase()
  if (window.XMLHttpRequest) {
    xhr = new XMLHttpRequest()
  } else {
    xhr = new ActiveXObject('Microsoft.XMLHttp')
  }
  xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && xhr.status == 200) {
      callback(xhr.responseText)
    }
  }

  if (method == 'GET') {
    var date = new Date(),
    timer = date.getTime()
    xhr.open('GET', url + '?' + data + '&timer' + timer, flag)
    xhr.send()
  } else if (method == 'POST') {
    xhr.open('POST', url, flag)
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
    xhr.send(data)
  }
}

29.实现bind()方法

Function.prototype.myBind = function (target) {
  var target = target || window
  var _args1 = [].slice.call(arguments, 1)
  var self = this
  var temp = function () {}
  var F = function () {
    var _args2 = [].slice.call(arguments, 0)
    var parasArr = _args1.concat(_args2)
    return self.apply(this instanceof temp ? this : target, parasArr)
  }
  temp.prototype = self.prototype
  F.prototype = new temp()
  return F
}

30.实现call()方法

Function.prototype.myCall = function () {
  var ctx = arguments[0] || window
  ctx.fn = this
  var args = []
  for (var i = 1; i < arguments.length; i++) {
    args.push(arguments[i])
  }
  var result = ctx.fn(...args)
  delete ctx.fn
  return result
}

31.实现apply()方法

Function.prototype.myApply = function () {
  var ctx = arguments[0] || window
  ctx.fn = this
  if (!arguments[1]) {
    var result = ctx.fn()
    delete ctx.fn
    return result
  }
  var result = ctx.fn(...arguments[1])
  delete ctx.fn
  return result
}

32.防抖

function debounce(handle, delay) {
  var timer = null
  return function () {
    var _self = this,
        _args = arguments
    clearTimeout(timer)
    timer = setTimeout(function () {
      handle.apply(_self, _args)
    }, delay)
  }
}

33.节流

function throttle(handler, wait) {
  var lastTime = 0
  return function (e) {
    var nowTime = new Date().getTime()
    if (nowTime - lastTime > wait) {
      handler.apply(this, arguments)
      lastTime = nowTime
    }
  }
}

34.格式化时间

function formatDate(t, str) {
  var obj = {
    yyyy: t.getFullYear(),
    yy: ("" + t.getFullYear()).slice(-2),
    M: t.getMonth() + 1,
    MM: ("0" + (t.getMonth() + 1)).slice(-2),
    d: t.getDate(),
    dd: ("0" + t.getDate()).slice(-2),
    H: t.getHours(),
    HH: ("0" + t.getHours()).slice(-2),
    h: t.getHours() % 12,
    hh: ("0" + t.getHours() % 12).slice(-2),
    m: t.getMinutes(),
    mm: ("0" + t.getMinutes()).slice(-2),
    s: t.getSeconds(),
    ss: ("0" + t.getSeconds()).slice(-2),
    w: ['日', '一', '二', '三', '四', '五', '六'][t.getDay()]
  }
  return str.replace(/([a-z]+)/ig, function ($1) {
    return obj[$1]
  })
}

35.验证邮箱的正则表达式

function isAvailableEmail(email) {
  var reg = /^([\w+\.])+@\w+([.]\w+)+$/
  return reg.test(email)
}

36.函数柯里化

//是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术
function curryIt(fn) {
  var length = fn.length,
      args = []
  var result = function (arg) {
    args.push(arg)
    length--
    if (length <= 0) {
      return fn.apply(this, args)
    } else {
      return result
    }
  }
  return result
}

37.大数相加

function sumBigNumber(a, b) {
  var res = '', //结果
      temp = 0; //按位加的结果及进位
  a = a.split('')
  b = b.split('')
  while (a.length || b.length || temp) {
    //~~按位非 1.类型转换,转换成数字 2.~~undefined==0 
    temp += ~~a.pop() + ~~b.pop()
    res = (temp % 10) + res
    temp = temp > 9
  }
  return res.replace(/^0+/, '')
}

38.单例模式

function getSingle(func) {
  var result
  return function () {
    if (!result) {
      result = new func(arguments)
    }
    return result
  }
}

39.localStorage/sessionStorage 增删查

function setStore(name, content, type = 'localStorage') {
  if (!name) return
  if (typeof content !== 'string') {
    content = JSON.stringify(content)
  }
  window[type] && window[type].setItem(name, content)
}

function getStore(name, parse = false, type = 'localStorage') {
  if (!name) return
  try {
    if (parse) {
      return window[type] && JSON.parse(window[type].getItem(name))
    }
  } catch (e) {
    return
  }
  return window[type] && window[type].getItem(name)
}

function removeStore(name, type = 'localStorage') {
  if (!name) return
  window[type] && window[type].removeItem(name)
}

40.输入一个值,返回其数据类型

function dataType(param) {
  return Object.prototype.toString.call(param)
}

41.获取当前日期

// separator 分隔符
function getCurrentDate(separator = '') {
  const oDate = new Date()
  const yyyy = oDate.getFullYear()
  let MM = oDate.getMonth() + 1
  let dd = oDate.getDate()
  if (MM < 10) {
    MM = '0' + MM
  }
  if (dd < 10) {
    dd = '0' + dd
  }
  return `${yyyy}${separator}${MM}${separator}${dd}`
}

持续更新中...