工具库

93 阅读2分钟

比较函数

Object.is()

console.log(Object.is(0, -0)); // false
console.log(Object.is(NaN, NaN)); // true

Object.is()用来比较两个值是否相等

simpleEqual

export function simpleEqual(x: unknown, y: unknown): boolean {
  if (x === y) {
    return true;
  } else {
    return false;
  }
}

console.log(isEqual(0, -0)); // true
console.log(isEqual(NaN, NaN)); // false

一般情况下通过全等判断就能解决相等问题,但是为了实现Object.is()的polyfill,需要对 0和-0 ,NaN和NaN 特殊处理

complicateEqual

export function complicateEqual(x: unknown, y: unknown): boolean {
  if (x === y) {
   // 比较 Infinity !== -Infinity 返回true,取反,返回false
    return !(x === 0 && 1 / x !== 1 / (y as number));
  } else {
  // NaN=== NaN 返回false,取反,返回true
    return !(x === x || y === y);
  }
}
console.log(complicateEqual(0, -0)); // false
console.log(complicateEqual(NaN, NaN)); //true

objectEqual


function objectEqual(
  a: Record<string, any> | null = {},
  b: Record<string, any> | null = {}
): boolean {
  // 处理 null
  if (!a || !b) return a === b;
  const aKeys = Object.keys(a).sort();
  const bKeys = Object.keys(b).sort();

  // 属性长度不相等
  if (aKeys.length !== bKeys.length) {
    return false;
  }
  return aKeys.every((key, i) => {
    const aVal = a[key];
    const bKey = bKeys[i];
    // 因为排序过,同一位置键名不相等
    if (bKey !== key) return false;
    const bVal = b[key];
    // 键值为null时
    if (aVal == null || bVal == null) return aVal === bVal;
    // 键值都为对象类型时
    if (typeof aVal === "object" && typeof bVal === "object") {
      return objectEqual(aVal, bVal);
    }
    // 最后一步可以根据需求采用不同逻辑
    // return aVal === bVal
    // return simpleEqual(aVal, bVal);
    // return complicateEqual(aVal, bVal);
    return String(aVal) === String(bVal);
  });
}
console.log(objectEqual({ a: 1 }, { a: 1 })); // true

自定义对象类型的比较

防抖函数

延迟执行

/**
 *  触发 debouncedFn,等待 wait 毫秒后, 执行 fn 函数,
 *  如果在此期间又触发了 debouncedFn ,则重新开始等待 wait 毫秒
 *  这样保证在wait 毫秒内仅执行一次 debouncedFn
 */
function debounce(fn: (...args: any[]) => any, wait = 0, thisArgs?: Object) {
  let debounceId: any = null;
  return (...args: any[]) => {
    if (debounceId) {
      globalThis.clearTimeout(debounceId);
    }
    debounceId = globalThis.setTimeout(() => {
      fn.apply(thisArgs, args);
    }, wait);
  };
}
function test(msg: string) {
  console.log("hello " + msg);
}

let debouncedFn = debounce(test, 2000);

let intervalId: any = null;
intervalId = setInterval(debouncedFn, 500, "world");

setTimeout(() => {
  clearInterval(intervalId);
}, 2000);

立即执行

export function debounce(
  fn: (...args: any[]) => any,
  wait = 0,
  immediate = false,
  thisArgs?: Object
) {
  let debounceId: any = null;
  return (...args: any[]) => {
    if (immediate) {
      let callNow = !debounceId;

      if (callNow) {
        debounceId = globalThis.setTimeout(() => {
          debounceId = null;
        }, wait);
        fn.apply(thisArgs, args);
      }
    } else {
      if (debounceId) {
        clearTimeout(debounceId);
      }
      debounceId = globalThis.setTimeout(() => {
        fn.apply(thisArgs, args);
      }, wait);
    }
  };
}

function test(msg: string) {
  console.log("hello " + msg);
}

let debouncedFn = debounce(test, 2000, true);

let intervalId: any = null;
intervalId = setInterval(debouncedFn, 500, "world");

setTimeout(() => {
  clearInterval(intervalId);
}, 2000);

事件绑定

export {};

interface EventListener {
  (evt: Event): void;
}

interface EventListenerObject {
  handleEvent(object: Event): void;
}

declare var window: any;
const addEvent = (() => {
  if (window.addEventListener) {
    return function (
      el: Node,
      eventName: string,
      handler: EventListener | EventListenerObject
    ) {
      el.addEventListener(eventName, handler);
    };
  } else if (window.attachEvent) {
    return function (
      el: any,
      eventName: string,
      handler: EventListener | EventListenerObject
    ) {
      el.attachEvent("on" + eventName, handler);
    };
  } else {
    return function (
      el: any,
      eventName: string,
      handler: EventListener | EventListenerObject
    ) {
      el["on" + eventName] = handler;
    };
  }
})();