js 手写题

1、实现curry

科里化(Currying) 是将一个接受多个参数的函数转换成一系列接受单一参数的函数的技术。换句话说,科里化将一个函数的多个参数“拆解”成多个函数,每个函数只接受一个参数,并且每个函数都返回一个接受下一个参数的函数,直到所有参数都被接收并返回最终结果。

function curry(fn, ...args1) {
  let argList = [...args1];

  // 返回一个新的函数
  return function (...args) {
    // 将当前传入的参数添加到参数列表中
    argList = [...argList, ...args];

    // 如果参数数量已经足够,则计算并返回结果
    if (argList.length >= fn.length) {
      return fn(...argList);  // 调用原始函数并传入所有参数
    } else {
      // 否则,返回一个新的函数,继续等待传入参数
      return curry(fn, ...argList);
    }
  };
}

// 示例:一个需要两个参数的函数
function add(a, b) {
  return a + b;
}

const curriedAdd = curry(add);

console.log(curriedAdd(2)(3)); // 输出 5

2、实现支持placeholder的curry()

本题的核心

  1. 参数收集逻辑

    • 每次调用都会检查是否收集了足够的非占位符参数

    • 如果足够,调用原函数

    • 如果不够,返回一个新函数继续收集

  2. 占位符替换

    • 在组合参数时,用实际参数按顺序替换占位符

    • 如果实际参数不足,保留占位符等待下次调用

const _ = Symbol("placehold")
function curry(fn) {
    return function curried(...args) {
      //  检查是否收集了足够的非占位符参数
      const sufficientArgs = args.length >= fn.length && 
      args.slice(0, fn.length).every(arg => arg !== _);
      // 1、判断是否是收集够了参数, 如果参数够了就掉用函数
      if (sufficientArgs) {
        return fn.apply(this, args.slice(0, fn.length));
      }

      // 2、否则,将函数按照传入顺序排序
      return function (...nextArgs) {
          let combins = [];
          let nextArgsIndex = 0
          args.forEach(item => {
            if (item === _ && nextArgsIndex < nextArgs.length) {
              combins.push(nextArgs[nextArgsIndex])
              nextArgsIndex++
            } else if (item !== _) {
              combins.push(item)
            } else {
              combins.push(_)
            }
          })

          if (nextArgsIndex < nextArgs.length) {
            combins = combins.concat(nextArgs.slice(nextArgsIndex))
          }
          return curried.apply(this, combins)
      }
    }
}

3、实现Array.prototype.flat() 函数

重点:

1、了解flat参数,deepth是铺平几层

function _flat(arrList, deepth) {
    if (!Array.isArray(arrList) || !arrList.length) return [];
    if (deepth === 0) return arrList;
    let arr = []
    arrList.forEach(item => {
        if (Array.isArray(item)) {
            arr = arr.concat(_flat(item, deepth - 1))
        } else {
            arr.push(item)
        }
    })
    return arr
}

4、手写throttle()

节流概念:

用于控制函数在一定时间间隔内只执行一次

可以用到节流技术的操作:

1、滚动

2、鼠标移动

3、窗口大小改变

let timed = null
function throttle(fn, delay) {
  return function () {
    if (!timed) {
      timed = setTimeout(() => {
        fn();
        clearTimeout(timed);
      }, delay);
    }
  }
}

5、手写debounce()

防抖概念:

当连续触发事件时,只有在事件停止触发一段时间后,才会执行处理函数

防抖应用场景:

1、搜索框

2、窗口大小调整

3、表单验证

let timed = null
function debounce(fn, delay) {
  return function () {
    if (timed) {
      clearTimeout(timed);
    }
    timed = setTimeout(() => {
      fn();
      timed = null;
    }, delay);
  }
}

6、手写debounce()并支持leading 和 trailing

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值