Skip to content

拼多多秋招笔试

  1. 确定输出

    🔍 展开代码
    1.html
    html
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <div id="parent">
            <button id="child">点击我</button>
        </div>
        <script>
            const parent = document.getElementById('parent');
            const child = document.getElementById('child');
    
            parent.addEventListener('click', (e) => {
    
                console.log('parent click', e.target, e.currentTarget);
    
            }, true)
    
            child.addEventListener('click', (e) => {
                console.log('child click', e.target, e.currentTarget);
            }, false)
        </script>
    </body>
    
    </html>
  2. 给定依赖树,输出最后的执行结果。

    🔍 展开代码
    1.js
    js
    /**
     * 按依赖顺序执行任务树
     * @param {Object} tree - 任务依赖关系树
     * tree 的结构示例:
     * {
     *   taskA: { task: async () => { ... }, dependencies: [] },
     *   taskB: { task: async () => { ... }, dependencies: ['taskA'] },
     *   taskC: { task: async () => { ... }, dependencies: ['taskA', 'taskB'] }
     * }
     */
    async function executeDependencyTree(tree) {
      const executedTask = new Set(); // 已经确定顺序的任务名称集合
      const queue = []; // 按依赖顺序排好的任务队列(数组)
    
      // 1. 初始化任务队列 —— 找到没有依赖的任务(即可以直接执行的)
      for (const taskName in tree) {
        if (
          !tree[taskName].dependencies ||
          tree[taskName].dependencies.length === 0
        ) {
          queue.push({ taskName, task: tree[taskName].task });
          executedTask.add(taskName);
        }
      }
    
      // 2. 循环查找剩下的任务
      // 条件:所有依赖任务都已经在 executedTask 里,才可以加入队列
      while (queue.length < Object.keys(tree).length) {
        for (const taskName in tree) {
          if (
            !executedTask.has(taskName) && // 没被处理过
            tree[taskName]?.dependencies.every((dep) => executedTask.has(dep)) // 依赖都已完成
          ) {
            queue.push({ taskName, task: tree[taskName].task });
            executedTask.add(taskName);
          }
        }
      }
    
      // 3. 按顺序执行队列里的任务
      const settledResults = await Promise.allSettled(
        queue.map((info) => info.task()),
      );
    
      // 4. 把执行结果整理成 { taskName: result } 的形式
      const result = {};
      queue.forEach((info, index) => {
        result[info.taskName] = settledResults[index];
      });
    
      return result;
    }
    
    // ============================
    // 👇 定义任务树
    // A -> B -> C 的依赖链
    // 其中 B 依赖 A,C 依赖 B
    // ============================
    
    const tree = {
      taskA: {
        task: async () => {
          console.log("执行 A");
          return "结果 A";
        },
        dependencies: [],
      },
      taskB: {
        task: async () => {
          console.log("执行 B");
          return "结果 B";
        },
        dependencies: ["taskA"],
      },
      taskC: {
        task: async () => {
          console.log("执行 C");
          return "结果 C";
        },
        dependencies: ["taskB"],
      },
    };
    
    // ============================
    // 👇 运行
    // ============================
    executeDependencyTree(tree).then((result) => {
      console.log("最终结果:", result);
    });
    
    // ============================
    // 👇 定义任务树(含失败任务)
    // A 正常执行
    // B 执行失败
    // C 依赖 B
    // ============================
    const _tree = {
      taskA: {
        task: async () => {
          console.log("执行 A");
          return "结果 A";
        },
        dependencies: [],
      },
      taskB: {
        task: async () => {
          console.log("执行 B");
          throw new Error("B 出错了!");
        },
        dependencies: ["taskA"],
      },
      taskC: {
        task: async () => {
          console.log("执行 C");
          return "结果 C";
        },
        dependencies: ["taskB"],
      },
    };
    
    // ============================
    // 👇 运行
    // ============================
    executeDependencyTree(_tree).then((result) => {
      console.log("最终结果:", result);
    });
  3. 区间合并

    🔍 展开代码
    2.js
    js
    function mergeIntervals(intervals) {
      if (intervals.length === 0) return [];
    
      // 1. 先按区间起点排序
      intervals.sort((a, b) => a[0] - b[0]);
    
      const result = [intervals[0]]; // 放入第一个区间
    
      for (let i = 1; i < intervals.length; i++) {
        let [left, right] = intervals[i];
        let last = result[result.length - 1];
    
        if (left <= last[1]) {
          // 有重叠,合并区间
          last[1] = Math.max(last[1], right);
        } else {
          // 没重叠,直接放进结果
          result.push([left, right]);
        }
      }
    
      return result;
    }
    
    const intervals = [
      [1, 3],
      [2, 6],
      [8, 10],
      [15, 18],
    ];
    const result = mergeIntervals(intervals);
    console.log(result);
  4. 手写路由匹配

    🔍 展开代码
    3.js
    js
    function createRouter() {
      const routesInfos = new Map();
    
      const addRoute = (path, view) => {
        routesInfos.set(path, view);
      };
    
      const match = (currentPath) => {
        // 先尝试完全匹配
        if (routesInfos.has(currentPath)) {
          const name = routesInfos.get(currentPath);
          return { name, params: null };
        }
    
        // 动态参数匹配
        for (const [path, view] of routesInfos.entries()) {
          const currentPathArr = currentPath
            .split("/")
            .filter((item) => item !== "");
          const pathArr = path.split("/").filter((item) => item !== "");
    
          if (currentPathArr.length !== pathArr.length) continue;
    
          const params = {};
          let matched = true;
    
          for (let i = 0; i < pathArr.length; i++) {
            const actual = currentPathArr[i];
            const expected = pathArr[i];
    
            if (expected.startsWith(":")) {
              params[expected.slice(1)] = actual;
            } else if (actual !== expected) {
              matched = false;
              break;
            }
          }
    
          if (matched) return { name: view, params };
        }
    
        // 没有匹配
        return null;
      };
    
      return { routesInfos, addRoute, match };
    }
    
    const router = createRouter();
    router.addRoute("/home", "HomePage");
    router.addRoute("/user/:id", "UserPage");
    
    console.log(router.match("/home"));
    console.log(router.match("/user/123"));
    console.log(router.match("/user/new/form"));