美文网首页
js高频手写功能总结

js高频手写功能总结

作者: Young_Jeff | 来源:发表于2021-09-01 14:49 被阅读0次

    1)防抖节流

    // 节流,一定时间内只执行第一个触发
    const throttle = (func, wait = 500) => {
     let lastTime = 0;
     return function (...args) {
       let now = new Date();
       if (now - lastTime > wait) {
         lastTime = now;
         func.apply(this,args);
       }
     };
    };
    // 防抖,一定时间只执行最近一次触发
    const debounce = (func, wait = 500) => {
     let timer = 0;
     return function (...args) {
       if (timer) clearTimeout(timer);
       timer = setTimeout(() => {
         func.apply(this,args);
       }, wait);
     };
    };
    
    

    2) 排序算法

    // 冒泡排序
    function bubbleSort(arr) {
      // 思路就是遍历数组,每次和右边的数字比大小,比之大就交换位置
      let length = arr.length;
      for (let i = 0; i <= length - 2; i++) {
        for (let j = i + 1; j <= length - 1; j++) {
          if (arr[i] > arr[j]) {
            [arr[i], arr[j]] = [arr[j], arr[i]];
          }
        }
      }
      return arr;
    }
    // console.log(bubbleSort(arr));
    // 快速排序,利用二分法
    // 会占用额外空间,不是最优解
    function quickSort(arr) {
      // 1.找一个标志位
      // 2.数组切成两半
      // 3.对left和right,递归使用相同条件
      // 终止条件
      if (arr.length <= 1) return arr;
      let flag = arr.shift();
      let left = [];
      let right = [];
      for (let i = 0; i < arr.length; i++) {
        console.log(arr[i]);
        if (arr[i] < flag) {
          left.push(arr[i]);
        } else {
          right.push(arr[i]);
        }
      }
      return quickSort(left).concat(flag, quickSort(right));
    }
    
    // 原地快排,不会占用额外空间
    let quickSort2 = (arr, low = 0, high = arr.length - 1) => {
      let left = low;
      let right = high;
      let flag = arr[left];
      if (low > high) return arr;
      while (left < right) {
        while (left < right && arr[right] > flag) {
          right--;
        }
        arr[left] = arr[right];
        while (left < right && arr[left] < flag) {
          left++;
        }
        arr[right] = arr[left];
      }
      arr[left] = flag;
      quickSort2(arr, low, left - 1);
      quickSort2(arr, left + 1, high);
      return arr;
    };
    

    3)柯里化函数

    let curry = (fn) => {
      return function curriedFn(...args) {
        console.log('形参个数', fn.length);
        if (args.length < fn.length) {
          return function () {
            return curriedFn(...args.concat(...arguments));
          };
        }
        return fn(...args);
      };
    };
    

    4)call

    // es3写法
    Function.prototype.es3call = function (context) {
      var content = context || window; //判断是否传递上下文,没有的话默认为全局作用域
      content.fn = this; //保存原来函数
      var args = [];
      // argument是一个伪数组,因为第一个参数是content,所以下标从1开始
      for (var i = 1; i < arguments.length; i++) {
        // 为啥不是直接 args.push(arguments[i]);
        // 因为那样如果参数传递字符串,类似这样传递
        // add.es3call(obj, '你好', '我好')
        // 导致eval在执行时,表达式变成了eval("obj.fn(你好,我好,)")
        // 对于eval而言就像传递了没加引号的字符串,所以就会报错
        // 而通过args.push('arguments[' + i + ']') 就可以先不解析
        // 遍历完的args长这样 ["arguments[1]","arguments[2]","arguments[3]"]
        // 当执行eval时,arguments[1]此时确实是作为一个变量存在,所以不会报错,于是被eval解析成了一个真正的字符传递给了函数
        args.push('arguments[' + i + ']');
      }
      // 利用eval函数,执行js代码
      // 此处使用eval是因为,数组不能直接作为参数传递给fn,而eval再执行时,会把变量转换成字符串,隐性执行了arr.toString()
      var result = eval('content.fn(' + args + ')');
      // 后面fn不需要了,删除
      delete content.fn;
      return result;
    };
    // es6写法
    Function.prototype.es6call = function (context) {
      const content = context || window;
      content.fn = this;
      const args = [];
      for (let i = 1; i < arguments.length; i++) {
        args.push(`arguments[${i}]`);
      }
      const result = content.fn(...args);
      delete content.fn;
      return result;
    };
    
    

    5)apply

    // apply实现
    // es3实现
    Function.prototype.es3Apply = function (context, arr) {
      var content = context || window;
      content.fn = this;
      var result;
      if (!arr) {
        result = content.fn();
      } else {
        var args = [];
        for (var i = 0; i < arr.length; i++) {
          args.push('arr[' + i + ']');
        }
        result = eval('content.fn(' + args + ')');
      }
    
      // 后面fn不需要了,删除
      delete content.fn;
      return result;
    };
    // es6实现
    Function.prototype.es6Apply = function (context, arr) {
      var content = context || window;
      content.fn = this;
      var result;
      if (!arr) {
        result = content.fn();
      } else {
        if (!(arr instanceof Array)) throw new Error('参数必须是数组');
        result = content.fn(...arr);
      }
      // 后面fn不需要了,删除
      delete content.fn;
      return result;
    };
    

    6)bind

    // bind实现
    Function.prototype.es6bind = function (context) {
      const content = context || window;
      const _this = this;
      const args = Array.prototype.slice.call(arguments, 1);
      return function () {
        return _this.apply(content, args.concat(...arguments));
      };
    };
    

    相关文章

      网友评论

          本文标题:js高频手写功能总结

          本文链接:https://www.haomeiwen.com/subject/zpmxwltx.html