前端高频面试题4:JavaScript场景题

发布于:2025-06-25 ⋅ 阅读:(22) ⋅ 点赞:(0)

  本专栏相关链接

前端高频面试题1:HTML/CSS

前端高频面试题2:浏览器/计算机网络

前端高频面试题3:JavaScript

1.使用js实现对象打平

/* 有如下对象
const obj = {
    a: {
        b: {
            c: 1
        }
    },
    d: {
        e: 2,
        f: 3
    },
    g: 4
};
将上述对象打平成如下结构
{
    a.b.c: 1,
    d.e: 2,
    d.f: 3,
    g: 4
} */
function flatObject(obj, key = '') {
  let newObj = {}
  for(let k in obj) {
    const path = key ? `${key}.${k}` : k
    if(typeof obj[k] === 'object') {
      newObj = {...newObj, ...flatObject(obj[k], path)}
    } else {
      newObj[path] = obj[k]
    }
  }
  return newObj
}
const obj = {
  a: {
      b: {
          c: 1
      }
  },
  d: {
      e: 2,
      f: 3
  },
  g: 4
};
console.log(flatObject(obj));

2.使用js遍历二叉树(前序、中序、后序、层序遍历)

// 前序遍历 根左右
var preorderTraversal = function(root) {
    let arr = []
    if(root) {
        arr.push(root.val)
        if(root.left) arr.push(...preorderTraversal(root.left))
        if(root.right) arr.push(...preorderTraversal(root.right))
    }
    return arr
};
// 中序遍历 左根右
var inorderTraversal = function(root) {
    let arr = []
    if(root) {
        if(root.left) arr.push(...inorderTraversal(root.left))
        arr.push(root.val)
        if(root.right) arr.push(...inorderTraversal(root.right))
    }
    return arr
}
// 后序遍历:左右根
var postorderTraversal = function(root) {
    let arr = []
    if(root) {
        if(root.left) arr.push(...postorderTraversal(root.left))
        arr.push(root.val)
        if(root.right) arr.push(...postorderTraversal(root.right))
    }
    return arr
}
// 层序遍历
var levelOrder = function(root) {
  const ret = [];
  if (!root) {
      return ret;
  }
  //首先根元素入队
  //当队列不为空的时候
  //  ·求当前队列的长度 s 
  //  ·依次从队列中取 s 个元素进行拓展,然后进入下一次迭代
  const q = [];
  q.push(root);
  while (q.length !== 0) {
      const currentLevelSize = q.length;
      ret.push([]);
      for (let i = 1; i <= currentLevelSize; ++i) {
          const node = q.shift();
          ret[ret.length - 1].push(node.val);
          if (node.left) q.push(node.left);
          if (node.right) q.push(node.right);
      }
  }
  return ret;
};

3.使用js实现一个有效括号的校验

var isValid = function(s) {
  const pairs = new Map([
      [')', '('],
      [']', '['],
      ['}', '{']
  ])
  let stk = [] // 使用栈
  s.split('').forEach(item => {
    if(pairs.has(item)) {
      if(!stk.length || stk[stk.length - 1] !== pairs.get(item)) {
        return false
      }
      stk.pop()
    } else {
      stk.push(item)
    }
  })
  return !stk.length
};

console.log(isValid('([)]'));

4.如何使用js实现一个Promise.allSettled

function allSettled(promises) {
  const res = promises.map(promise => {
    return Promise.resolve(promise).then(
      value => ({ status: 'fulfilled', value }),
      reason => ({ status: 'rejected', reason })
    )
  })
  return Promise.all(res)
}

const p1 = Promise.resolve(1);
const p2 = Promise.reject('Error');
const p3 = 42;

allSettled([p1, p2, p3]).then(console.log);

5. 实现一个并发请求控制,同时最多请求n个,响应后补充一个,并实现可以通过await接收结果

function timeout(time,name) {
  return new Promise(resolve => {
    setTimeout(() => resolve(name), time)
  })
}

class SuperTask {
  constructor(maxNum) {
    this.maxNum = maxNum
    this.taskList = []
    this.runningTask = 0
  }
  add(task) {
    return new Promise((resolve, reject) => {
      this.taskList.push({task, resolve, reject});
      this._run()
    })
  }

  _run() {
    while(this.runningTask < this.maxNum && this.taskList.length) {
      const {task, resolve, reject} = this.taskList.shift()
      task().then(resolve, reject).finally(() => {
        this.runningTask--
        this._run()
      })
      this.runningTask++
    }
  }
}
const superTask = new SuperTask(2)
function addTask(time, name) {
  superTask.add(() => timeout(time, name)
  ).then(res => {
    console.log(`任务${res}完成`);
  })
}

addTask(10000, 1);
addTask(5000, 2);
addTask(3000, 3);
addTask(4000, 4);
addTask(5000, 5);


网站公告

今日签到

点亮在社区的每一天
去签到