高级前端手写面试题

本文详细探讨了前端面试中常见的手写题目,包括树形结构转列表、对象数组转树形结构、实现ES6的extends、手写Promise.race、debounce、数组方法、深拷贝、链表操作、Cookie处理、滚动加载、正则表达式应用等,覆盖了前端开发的多个核心知识点。

树形结构转成列表(处理菜单)

[
    {
   
   
        id: 1,
        text: '节点1',
        parentId: 0,
        children: [
            {
   
   
                id:2,
                text: '节点1_1',
                parentId:1
            }
        ]
    }
]
转成
[
    {
   
   
        id: 1,
        text: '节点1',
        parentId: 0 //这里用0表示为顶级节点
    },
    {
   
   
        id: 2,
        text: '节点1_1',
        parentId: 1 //通过这个字段来确定子父级
    }
    ...
]

实现代码如下:

function treeToList(data) {
   
   
  let res = [];
  const dfs = (tree) => {
   
   
    tree.forEach((item) => {
   
   
      if (item.children) {
   
   
        dfs(item.children);
        delete item.children;
      }
      res.push(item);
    });
  };
  dfs(data);
  return res;
}

前端手写面试题详细解答

对象数组列表转成树形结构(处理菜单)

[
    {
   
   
        id: 1,
        text: '节点1',
        parentId: 0 //这里用0表示为顶级节点
    },
    {
   
   
        id: 2,
        text: '节点1_1',
        parentId: 1 //通过这个字段来确定子父级
    }
    ...
]

转成
[
    {
   
   
        id: 1,
        text: '节点1',
        parentId: 0,
        children: [
            {
   
   
                id:2,
                text: '节点1_1',
                parentId:1
            }
        ]
    }
]

实现代码如下:

function listToTree(data) {
   
   
  let temp = {
   
   };
  let treeData = [];
  for (let i = 0; i < data.length; i++) {
   
   
    temp[data[i].id] = data[i];
  }
  for (let i in temp) {
   
   
    if (+temp[i].parentId != 0) {
   
   
      if (!temp[temp[i].parentId].children) {
   
   
        temp[temp[i].parentId].children = [];
      }
      temp[temp[i].parentId].children.push(temp[i]);
    } else {
   
   
      treeData.push(temp[i]);
    }
  }
  return treeData;
}

实现ES6的extends

function B(name){
   
   
  this.name = name;
};
function A(name,age){
   
   
  //1.将A的原型指向B
  Object.setPrototypeOf(A,B);
  //2.用A的实例作为this调用B,得到继承B之后的实例,这一步相当于调用super
  Object.getPrototypeOf(A).call(this, name)
  //3.将A原有的属性添加到新实例上
  this.age = age; 
  //4.返回新实例对象
  return this;
};
var a = new A('poetry',22);
console.log(a);

实现apply方法

apply原理与call很相似,不多赘述

// 模拟 apply
Function.prototype.myapply = function(context, arr) {
  var context = Object(context) || window;
  context.fn = this;

  var result;
  if (!arr) {
    result = context.fn();
  } else {
    var args = [];
    for (var i = 0, len = arr.length; i < len; i++) {
      args.push("arr[" + i + "]");
    }
    result = eval("context.fn(" + args + ")");
  }

  delete context.fn;
  return result;
};

手写 Promise.race

该方法的参数是 Promise 实例数组, 然后其 then 注册的回调方法是数组中的某一个 Promise 的状态变为 fulfilled 的时候就执行. 因为 Promise 的状态只能改变一次, 那么我们只需要把 Promise.race 中产生的 Promise 对象的 resolve 方法, 注入到数组中的每一个 Promise 实例中的回调函数中即可.

Promise.race = function (args) {
   
   
  return new Promise((resolve, reject) => {
   
   
    for (let i = 0, len = args.length; i < len; i++) {
   
   
      args[i].then(resolve, reject)
    }
  })
}

debounce(防抖)

触发高频时间后n秒内函数只会执行一次,如果n秒内高频时间再次触发,则重新计算时间。

const debounce = (fn, time) => 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值