常用手写代码

debounce防抖

监听一个输入框的,文字变化后触发change事件。 直接用keyup 事件,则会频发触发change事件。

防抖:用户输入结束或暂停时,才会触发change事件

const input1 = document.getElementById("input1 ");
let timer = null;

// input1.addEventListener("keyup ", function () {
//   if (timer) {
//     clearTimeout(timer);
//   }
//   timer = setTimeout(() => {
//     //模拟触发change 事件
//     console.log(input1.value);
//     //清空定时器
//     timer = null;
//   }, 500);
// });

function debounce(fn, delay = 500) {
  // timer 是闭包中的
  let timer = null;
  return function () {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      fn.apply(this, arguments);
      timer = null;
    }, delay);
  };
}

input1.addEventListener(
  "keyup",
  debounce(() => {
    console.log(input1.value);
  }),
  600
);

throttle节流

场景:拖拽一个元素时,要随时拿到该元素被拖拽的位置, 直接用drag事件,则会频发触发,很容易导致卡顿。

节流:无论拖拽速度多快,都会每隔100ms触发一次

const div1 = document.getElementById("div1");

//节流 定时器
function throttle(fn, delay = 100) {
  let timer = null;
  return function () {
    if (timer) {
      return;
    }
    timer = setTimeout(() => {
      fn.apply(this, arguments);
      timer = null;
    }, delay);
  };
}

div1.addEventListener(
  "drag ",
  throttle(function (e) {
    console.log(e.offsetx, e.offsetY);
  })
);

/* 节流 时间戳
function throttle(fn, delay) {
  let last = 0;
  return function() {
    // js在某个数据类型前使用‘+’,这个操作目的是为了将该数据类型转换为Number类型,
    // 如果转换失败,则返回NaN;
    const now = +new Date();
    const offset = now - last;
    if (offset > delay) {
      last = now;
      fn.apply(this, arguments);
    }
  };
}
*/

isEqual深度比较

function isObject(obj) {
  return typeof obj === "object" && obj !== null;
}

function isEqual(obj1, obj2) {
  if (!isObject(obj1) || !isObject(obj2)) {
    //值类型(注意,参与equal的一般不会是函数)
    return obj1 === obj2;
  }
  if (obj1 === obj2) {
    return true;
  }
  //两个都是对象或数组,而且不相等
  // 1。先取出 obj1和 obj2的keys ,比较个数
  const obj1Keys = Object.keys(obj1);
  const obj2Keys = Object.keys(obj2);
  if (obj1Keys.length !== tobj2Keys.length) {
    return false;
  }
  //2.以obj1 为基准,和obj2一次递归比较
  for (let key in obj1) {
    //比较当前key 的val一递归!!!
    const res = isEqual(obj1[key], obj2[key]);
    if (!res) {
      return false;
    }
  }
  // 3.全相等
  return true;
}

//测试
const obj1 = {
  a: 100,
  b: {
    x: 100,
    y: 200,
  },
};
const obj2 = {
  a: 100,
  b: {
    x: 100,
    y: 200,
  },
};

flat数组拍平-值类型

function flat(arr) {
  //验证arr 中,还有没有深层数组[1,2,[3,4]]
  const isDeep = arr.some((item) => item instanceof Array);
  if (!isDeep) {
    return arr; // 已经是flatern [1,2,3,4]
  }
  const res = Array.prototype.concat.apply([], arr);
  return flat(res); //递归
}
const res = flat([1, 2, [3, 4], 5]);
console.log(res); // [1, 2, 3, 4, 5]

deepClone深拷贝

function deepClone(obj = {}) {
  if (typeof obj !== "object" || obj == null) {
    // obj是null ,或者不是对象和数组,直接返回
    return obj;
  }

  // 初始化返回结果
  let result;
  if (obj instanceof Array) {
    result = [];
  } else {
    result = {};
  }

  for (let key in obj) {
    // 保证key 不是原型的属性
    if (obj.hasOwnProperty(key)) {
      // 递归调用!!!
      result[key] = deepClone(obj[key]);
    }
  }
  //返回结果
  return result;
}

bind

Function.prototype.band1 = function () {
  // 将参数拆解为数组
  const args = Array.prototype.slice.call(arguments);

  // 获取 this (数组第一项)
  const t = args.shift();

  // fn1.bind(...) 中的 fn1
  const self = this;

  return function () {
    return self.apply(t, args);
  };
};

trim

String.prototype.trim = function () {
  return this.replace(/一\s+/, " ").replace(/\s+$/, "");
};

jQuery考虑插件和扩展性

class jQuery {
  constructor(selector) {
    const result = document.querySelectorAll(selector);
    const length = result.length;
    for (let i = 0; i < length; i++) {
      this[i] = result[i];
    }
    this.length = length;
    this.selector = selector;
  }
  get(index) {
    return this[index];
  }
  each(fn) {
    for (let i = 0; i < this.length; i++) {
      const elem = this[i];
      fn(elem);
    }
  }
  on(type, fn) {
    return this.each((elem) => {
      elem.addEventListener(type, fn, false);
    });
  }
  // 扩展很多 DOM API
}

// 插件
jQuery.prototype.dialog = function (info) {
  alert(info);
};

// “造轮子”
class myJQuery extends jQuery {
  constructor(selector) {
    super(selector);
  }
  // 扩展自己的方法
  addClass(className) {}
  style(data) {}
}

// const $p = new jQuery('p')
// $p.get(1)
// $p.each((elem) => console.log(elem.nodeName))
// $p.on('click', () => alert('clicked'))
最后更新时间:
贡献者: DESKTOP-ER5718D\zt