美文网首页
【前端】interview时碰到的js手写题

【前端】interview时碰到的js手写题

作者: Q小予o0 | 来源:发表于2021-08-13 15:23 被阅读0次

*多个实现异步的方法

  • Promise.all(iterable)实现,同步执行完所有参数里的promise任务,再继续执行then的异步任务
// promise.all同步任务
const promiseMain = (index) => {
    return new Promise((resolve,reject)=>{
        setTimeout(() => {
            resolve(index)
            console.log('同步promise.all',index, new Date());
        }, 500);
    })
}

// 生成全部异步操作
const task = []
for (let i=0;i<4;i++) {
  task.push(promiseMain(i))
}
// 同步执行完异步操作后输出done
Promise.all(task).then(r=> console.log("all task done!",r));
  • reduce实现异步,在上个请求执行后 按顺序执行代码 而不会一下子执行全部请求
task.reduce((pre,curr)=>{
    return pre.then((r)=> {
        return new Promise((resolve, reject) => {
            setTimeout(async () => {
                console.log('异步',await curr, new Date())
                resolve()
              }, 1000)
        })
    })
},Promise.resolve())
  • for循环实现多个异步方法
for (let i =0; i<task.length;i++ ) {
    (function(j){
        setTimeout(async() => {
            console.log('异步',await task[j], new Date())
        }, 1000*j)
    })(i)   // 立即调用绑定当前索引
}
image.png

*数组去重

  • new Set去重,new set之后是一个类数组
let arr = [1,2,3,5,3,4,4,1]
 // 可以...扩展运算符解构
arr = [...new Set(arr)]   //  [1,2,3,5,4]
 // 或者用Array.from从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组
Array.from(new Set(arr))  //  [1,2,3,5,4]
  • reduce 去重
let arr = [1,2,3,5,3,4,4,1]
arr = arr.reduce((pre,curr)=> pre.concat(pre.includes(curr)?[]:curr),[])
//  [1,2,3,5,4]

*使定时器没有回调,不需要处理任务,只需要等“一秒”,类似于sleep

const delay = (time) => {
    return new Promise((resolve) => {setTimeout(resolve, time);})
}
console.log(111);
await delay(1000);
console.log(333);
image.png

*组合数组,两个数组交叉合并

let arr = [1,3,5,7];
let arr2 = [2,4,6,8,9];
const compose = (arr,arr2) => {
  if (!Array.isArray(arr) || !Array.isArray(arr2)) return;
  let newArr = []
  const minLength = Math.min(arr.length,arr2.length);
  for (let i=0;i<minLength;i++) {
    newArr.push(arr[i]);
    newArr.push(arr2[i]);
  }
  newArr = arr.length>arr2.length ? newArr.concat(arr.slice(minLength)):newArr.concat(arr2.slice(minLength));
  return newArr
}
compose(arr,arr2);  // [1,2,3,4,5,6,7,8,9]

*写个方法实现a的幂次方, 传入两个值a ,b, b代表几次幂,求a的幂次方结果。

function getAdd(a, b) {
    let abs = Math.abs(b);  // 取b的正整数
    let result = 1;
    for (let i = 0; i < abs; i++) {
      result *= a;
    }
    if (b < 0) {
      result = 1 / result;
    }
    return result
}
image.png

*拍平一个数组,并求和。

const arr = [8, 12,4,[5, 9, 4], 1, 3, [7, 5, 10, [3, 4, 6, 2]], 4, 3, 2, 4];

function minArr(arr) {
    if (!Array.isArray(arr)) return;
   const a=  arr.reduce((init,curr) => Array.isArray(curr)?init.concat(minArr(curr)):init.concat(curr),[]);
   return a
}

console.log(minArr(arr))  // 拍平数组后
const sum = minArr(arr).reduce((init,curr)=>init+curr,0);
console.log(sum) 
image.png

*防抖函数

  • 所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
  • 也直接引用import { debounce } from 'lodash';
const  dounce = (fn,time) => {
  let timeOut;
  let that = this;
  return function () {
      if (timeOut) clearTimeout(timeOut);
      timeOut = setTimeout(() => {
        fn.apply(that,arguments)
      }, time);
  }
}

用防抖函数监听浏览器窗口变化

window.addEventListener('resize', debounce((event)=>{
  console.log(event)
},500))

*节流函数

  • 所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
const throttle = (func, time) => {
    let canDo = true;
     let that = this;
    return function() {
        if (!canDo) return;
        canDo = false;
        setTimeout(() => {
            func.apply(that.arguments)
            canDo = true
        }, time);
    }
}

*函数柯里化求和

const sum = (...arg) => {
 let x = arg.reduce((init,curr)=>init+curr);
 return function (...arg2) {
     if (arg2.length === 0) return x;
     let y = arg2.reduce((init,curr)=>init+curr);
     return sum(x+y)
 }
}
console.log(sum(1,2,2,5)(7)()) // 17

*实现 bind ()

Function.prototype.MyBind = function (context, ...args) {
  let self = this;
  return function() {
    return self.apply(context, args);
  }
}

// test
let a = {name: 'jack'} 
let test = function() {
  console.log(this.name); // jack
}
let rs = test.MyBind(a);
rs();

*实现深拷贝

  • 常用方法JSON.parse(JSON.stringify())
  • 使用lodash 的深拷贝函数。
  • 手写deepClone
const deepClone = (obj) => {
//   通过从原型上判断对象还是数组
  const copy = obj instanceof Array ? []:{};
  for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
          // obj[key] 是否是对象,如果是对象,递归遍历
          copy[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
      }
  }
  return copy
}
let b = {name: 'jack', birth: {year: '1997', month: '10'}}
let c = deepClone(b);
b.name = 'nacy';
// b 的name变了,但c还是原来的name
// b.name: nacy     ----c.name: jack

*二维数组转树形结构数组

let arr = [
    {
        "id": "01", 
        "name": "公司", 
    }, 
    {
        "id": "02", 
        "parentId": "01", 
        "name": "一级部门", 
    }, 
    {
        "id": "30", 
        "parentId": "02", 
        "name": "二级部门", 
    }, 
    {
        "id": "31", 
        "parentId": "02", 
        "name": "二级部门", 
    }, 
    {
        "id": "40", 
        "parentId": "30", 
        "name": "三级部门", 
    }, 
    { 
        "id": "41", 
        "parentId": "30", 
        "name": "三级部门", 
    }
];
function getTree(arr) {
  if (!Array.isArray(arr)) return;
  const parents = arr.filter(f=>!f.parentId);
  const children = arr.filter(c=>c.parentId !== undefined && c.parentId !== null);
  //定义转换方法的具体实现
    let translator = (parents, children) => {
        //遍历父节点数据
        parents.forEach((parent) => {
          //遍历子节点数据
          children.forEach((current, index) => {
            //此时找到父节点对应的一个子节点
            if (current.parentId === parent.id) {
              //对子节点数据进行深拷贝,不影响原数据
              let temp = JSON.parse(JSON.stringify(children))
              //让当前子节点从temp中移除,temp作为新的子节点数据,这里是为了让递归时,子节点的遍历次数更少,如果父子关系的层级越多,越有利
              temp.splice(index, 1)
              //把找到子节点放入父节点的children属性中
              typeof parent.children !== 'undefined' ? parent.children.push(current) : parent.children = [current];
             //让当前子节点作为唯一的父节点,去递归查找其对应的子节点
              translator([current], temp)
            }
          }
          )
        }
        )
      }
    //调用转换方法
  translator(parents, children)
 
  //返回最终的结果
  return parents
}
getTree(arr)

相关文章

网友评论

      本文标题:【前端】interview时碰到的js手写题

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