前端八股文-常用工具函数实现(深拷贝、发布订阅、节流、防抖、懒加载)

2,310 阅读1分钟

系列文章

前端八股文-类型判断

前端八股文-原型链

前端八股文-继承

前端八股文-手写new、bind、call、apply的三两事

深拷贝

function deep(obj) {
        if (!obj || typeof obj !== 'object') {
            return obj;
        }
        let objClone = Array.isArray(obj) ? [] : {};
        if (obj && typeof obj === 'object') {
            for (let key in obj) {
                if (obj.hasOwnProperty(key)) {
                    if (obj[key] && typeof obj[key] === 'object') {
                        objClone[key] = deep(obj[key])
                    } else {
                        objClone[key] =  obj[key]
                    }
                }
            }
        }
        return objClone
    }

对象扁平化({dto: {name:1}})=> {dto: {name:1},dtoName: 1}

  function flatObj(obj, keyName) {
        if (!obj || typeof obj !== 'object') {
            return obj;
        }
        let finallyData = {}
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                const newKeyName = keyName ? keyName + key.substring(0, 1).toUpperCase() + key.substring(1) : key
                if (obj[key] && typeof obj[key] !== 'object' || Array.isArray(obj[key]) || Object.keys(obj[key]).length === 0) {
                    finallyData[newKeyName] = obj[key]
                } else {
                    finallyData = Object.assign({}, finallyData, flatObj(obj[key], newKeyName))
                }
            }
        }
        return finallyData
    }

eventbus(简单的发布订阅模式)

class EventBus {
    constructor() {
        EventBus.EventStore = {
            $uid: 0
        };
    }

    on(type, handler) {
        let cache = EventBus.EventStore[type] || (EventBus.EventStore[type] = {});
        handler.$uid = handler.$uid || EventBus.EventStore.$uid++;
        cache[handler.$uid] = handler;
    }

    emit(type, ...param) {
        let cache = EventBus.EventStore[type],
            key,
            tmp;

        if (!cache) return;

        for (key in cache) {
            tmp = cache[key];
            tmp.call(this, ...param);
        }
    }

    off(type, handler) {
        let counter = 0,
            cache = EventBus.EventStore[type];

        if (handler == null) {
            if (!cache) return true;
            return !!EventBus.EventStore[type] && (delete EventBus.EventStore[type]);
        } else {
            !!EventBus.EventStore[type] && (delete EventBus.EventStore[type][handler.$uid]);
        }

        for (const key in cache) {
            counter++;
        }

        return !counter && (delete EventBus.EventStore[type]);
    }
}

节流(原理:在规定时间内只触发一次)

function throttle (fn, delay) {
  // 利用闭包保存时间
  let prev = Date.now()
  return function () {
    let context = this
    let arg = [...arguments]
    let now = Date.now()
    if (now - prev >= delay) {
      fn.apply(context, arg)
      prev = Date.now()
    }
  }
}

防抖(原理:在规定时间内未触发第二次,则执行)

function debounce(fn, delay) {
    let timer = null;
    return function() {
    let args = [...arguments];
    let context = this;
    clearTimeout(timer);
    timer = setTimeout(() =>{
        fn.apply(context, arg)
    }, delay)
    }
}

懒加载

let imgs =  document.querySelectorAll('img')
// 可视区高度
let clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
function lazyLoad () {
  // 滚动卷去的高度
  let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
  for (let i = 0; i < imgs.length; i ++) {
    // 图片在可视区冒出的高度
    let x = clientHeight + scrollTop - imgs[i].offsetTop
    // 图片在可视区内
    if (x > 0 && x < clientHeight+imgs[i].height) {
      imgs[i].src = imgs[i].getAttribute('data')
    } 
  }      
}
// addEventListener('scroll', lazyLoad) or setInterval(lazyLoad, 1000)