常见实现题

1. js限制并发请求

核心:

  • 用缓冲队列存储请求
  • 记录当前正在执行的请求数量
  • run函数【判断个数是否在最大并发数内, 是则发请求并在结束回调内更改计数,并递归调起下一个请求】
class BufferControl {
    bufferList = []; //缓冲队列
    maxLen = 1; //当前允许执行的最大并发数量
    currentQueenCount = 0; //当前正在执行的任务数量
    add(fn) {
        this.bufferList.push(fn);
        this.run();
    }

    run() {
        if (!this.bufferList.length) {
            return;
        }
        while (this.bufferList.length && this.currentQueenCount < this.maxLen) {
            let fn = this.bufferList.shift();
            this.currentQueenCount++;
            fn().then(() => {
                this.currentQueenCount--;
                this.run();
            });
        }
    }
}
const reqs = new Array(10).fill(false).map((_, i) =>
    () => new Promise(resolve => setTimeout(() => { console.log(i); resolve(i) }, 1000)))

const executeSerialMax = (reqs, max) => {
    let curRequestCount = 0;

    const run = function () {
        if (!reqs.length) return;

        while (reqs.length && curRequestCount < max) {
            // console.log(new Date())
            const task = reqs.shift();
            curRequestCount++;
            task().then().finally(_ => {
                curRequestCount--;
                run();
            })
        }
    }

    run();
}

executeSerialMax(reqs, 3)

2. 合法的URL

// 补全代码
// 开始符 ^
// 协议部分http(s)://        表示为((https|http|ftp|rtsp|mms)?:\/\/)
// 域名部分                  表示为(([A-Za-z0-9]+-[A-Za-z0-9]+|[A-Za-z0-9]+)\.)+
// 顶级域名com cn等为2-6位   表示为([a-zA-Z]{2,6})
// 端口部分                  表示为(:\d+)?, ?表示0次或1次
// 请求路径如/login          表示为 (\/.*)?
// 问号传参及哈希值如?age=1   表示为 (\?.*)?和(#.*)?
// 结束符 $
const _isUrl = url => {
    return /^((http|https):\/\/)?(([A-Za-z0-9]+-[A-Za-z0-9]+|[A-Za-z0-9]+)\.)+([A-Za-z]+)(:\d+)?(\/.*)?(\?.*)?(#.*)?$/.test(url)
}

3. 获取地址栏中的参数

var str = "http://www.baidu.com?id=51028857&name=ceshi&age=8";
var reg = /([^?=&]+)=([^?=&]+)/g;
var result = {};
str.replace(reg, function ($1, $2, $3) {
    result[$2] = $3;
});
console.log(result);

4. 数组去重

function repeatDel(arr) {
    let set = new Set(arr);
    return Array.from (set);
}
// console.log(repeatDel([1,1,2,2,3,4,5,4,3,3,2,1]));

function repeatDel_second(arr) {
    let hasNum = {};
    let newArr = [];
    arr.forEach(item => {
        !hasNum[item] ? ((hasNum[item] = true), (newArr.push(item))) : "";
    });
    return newArr;
}
// console.log(repeatDel_second([1,1,2,2,3,4,5,4,3,3,2,1]));

5. 扁平化

// 1. ...
// 二维变一维
Array.prototype.concat.apply([], [1,2,3,[4,5]]);
[].concat(...[1,2,3,[4,5]]);
// 多维
function flatten(arr) {
  while(arr.some(item => Array.isArray(item))) {
    arr = [].concat(...arr);
  }
  return arr;
}

// 2. 递归

function flatten1(arr) {
  let result = [];
  arr.map(item => {
    if (Array.isArray(item)) {
      result = result.concat(flatten1(item));
    } else {
      result.push(item);
    }
  })
  return result;
}

// join split
// 注释
// var arr = [1,2,[3,[4,[5]]]];
// arr.join(",");
// "1,2,3,4,5"
// arr.toString()
// "1,2,3,4,5"
function flatten2(arr) {
  return arr.join(",").split(",").map(item => parseInt(item));
}

// toString split
function flatten3(arr) {
  return arr.toString().split(",").map(item => parseInt(item));
}

// reduce
function flatten4(arr) {
  return arr.reduce((result, item) => {
    return result.concat(Array.isArray(item) ? flatten4(item) : item);
  }, [])
}

function flatten5(arr) {
  // 扩展运算符实现扁平化
  // while(arr.some(item => Array.isArray(item))) {
  //   arr = [].concat(...arr);
  // }
  // return arr;
  // 递归
  // let result = [];
  // arr.map(item => {
  //   if(Array.isArray(item)) {
  //     result = result.concat(flatten5(item));
  //   } else {
  //     result.push(item);
  //   }
  // })
  // return result;
  // reduce
  // return arr.reduce((result, item) => {
  //   return result.concat(Array.isArray(item) ? flatten5(item) : item);
  // }, []);
}


数组转树

const data =
    [{ "id": 1, "parentId": null, "value": 1 }, { "id": 2, "parentId": 3, "value": 2 }, { "id": 3, "parentId": 1, "value": 3 }, { "id": 4, "parentId": 2, "value": 4 }];
    
function generateTree(data) {
    let res = {};
    const hash = {};
    for (let i = 0; i < data.length; i++) {
        hash[data[i].id] = { ...data[i] };
    }
    for (let i = 0; i < data.length; i++) {
        let obj = data[i];
        if (obj.parentId === null) {
            res = hash[obj.id];
        } else {
            !hash[obj.parentId].children && (hash[obj.parentId].children = []);
            // 注意push的是新拷贝的hash
            hash[obj.parentId].children.push(hash[obj.id]);
        }
    }
    return res;
}

console.log(generateTree(data))

防抖

短时间内连续触发的事件,重新触发事件就重新开始计时。

function debounce(fn, delay) {
    let timer;

    return function(args) {
        const _this = this;
       t
        timer = setTimeout(() => {
            fn.apply(_this, args)
        }, delay)
    }
}

节流

让某个时间期限内,事件处理函数只执行一次。

function throttle(fn, wait) {
    let timeout;

    return function(args) {
        const _this = this;
        if(!timeout) {
            timeout = setTimeout(() => {
                timeout = null;
                fn.apply(_this, args);
            }, wait);
        }
    }
}

持续更新中…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值