各种手写

如题

Posted by hdj on August 2, 2022

1.compose

    function compose(...fn){
     if (!fn.length) return (v) => v;
     if (fn.length === 1) return fn[0];
        return fn.reduce((total,current)=>{
            return (args)=>{
                total(current(args))
            }
        })
        
    }
 

使用案例解析

   let x = 10
function fn1 (x) {return x + 1}
function fn2(x) {return x + 2}
function fn3(x) {return x + 3}
function fn4(x) {return x + 4}

// 假设我这里想求得这样的值
let a = fn1(fn2(fn3(fn4(x)))) // 10 + 4 + 3 + 2 + 1 = 20

 

异步版本

2. settimeout 模拟实现 setinterval(带清除定时器的版本)

    function mySettimeout(fn,wait){
        let timer = null
        function inverval(){
            fn()
            timer = setTimeout( inverval,wait)
        }    
        inverval()
        return {
            cancel: function(){
              timer && clearTimeout(timer)
            }
        }
        
    }
    
     var c=mySettimeout(()=>{
       console.log(111);
    },1000)
   
 

我们能反过来使用 setinterval 模拟实现 settimeout 吗?

 
    function myIntevalSettimeout(fn,wait){
        let timer = setInteval((){
         clearInterval(timer)

         fn()
        },wait)
      
        return {
            cancel: function(){
              timer && clearInterval(timer)
            }
        }
        
    }
    
     var c=myIntevalSettimeout(()=>{
       console.log(111);
    },1000)
   
 

3 发布订阅模式

  class EventEmitter {
      constructor() {
        this.events = {};
      }
      // 实现订阅
      on(type, callBack) {
        if (!this.events[type]) {
          this.events[type] = [callBack];
        } else {
          this.events[type].push(callBack);
        }
      }
      // 删除订阅
      off(type, callBack) {
        if (!this.events[type]) return;
        this.events[type] = this.events[type].filter((item) => {
          return item !== callBack;
        });
      }
      // 只执行一次订阅事件
      once(type, callBack) {
        const that = this
        function fn() {
          callBack();
          that.off(type, fn);
        }
        this.on(type, fn);
      }
      // 触发事件
      emit(type, ...rest) {
        this.events[type] &&
          this.events[type].forEach((fn) => fn.apply(this, rest));
      }
    }

4 数组去重

    function uniqueArr(arr) {
         return [...new Set(arr)];
    }

5 数组扁平化

   function flatter(arr) {
      if (!arr.length) return;
      return arr.reduce(
        (pre, cur) =>{
             return  pre.concat(Array.isArray(cur) ?flatter(cur): [cur]
        }, 
        []
      );
   }

6 寄生组合继承

    function Parent(name) {
      this.name = name;
      this.say = () => {
        console.log(111);
      };
    }
    Parent.prototype.play = () => {
      console.log(222);
    };
    
    function Children(name) {
      Parent.call(this);
      this.name = name;
    }
    
    Children.prototype = Object.create(Parent.prototype);
    Children.prototype.constructor = Children;

7 题目描述:JS 实现一个带并发限制的异步调度器 Scheduler,保证同时运行的任务最多有两个


    class Scheduler {
      constructor(limit) {
        this.queue = [];
        this.maxCount = limit;
        this.runCounts = 0;
      }
      add(time, order) {
        const promiseCreator = () => {
          return new Promise((resolve, reject) => {
            setTimeout(() => {
              console.log(order);
              resolve();
            }, time);
          });
        };
        this.queue.push(promiseCreator);
      }
      taskStart() {
        for (let i = 0; i < this.maxCount; i++) {
          this.request();
        }
      }
      request() {
        if (!this.queue || !this.queue.length || this.runCounts >= this.maxCount) {
          return;
        }
        this.runCounts++;
        this.queue
          .shift()()
          .then(() => {
            this.runCounts--;
            this.request();
          });
      }
    }
    const scheduler = new Scheduler(2);
    const addTask = (time, order) => {
      scheduler.add(time, order);
    };
    addTask(1000, "1");
    addTask(500, "2");
    addTask(300, "3");
    addTask(400, "4");
    scheduler.taskStart();

简易版


const fns = [0,1,2,3,4,5].map((item)=>{
    return new Promise((resolve)=>{
        setTimeout(()=>{
            resolve(item)
        }, item *100)
    })
})

function limtPromise(promises, limit = 2){
    let total = promises.length
    let index = 0 
    let queue = []
    function run(){
        if(index>= total){
            return
        }
        return new Promise((resolve)=>{
            queue.push(promises[index])
            resolve(promises[index])
        }).then((val)=>{
            console.log(val, queue,queue.length)
        }).finally(()=>{
            index ++
            queue.shift()
            if(index< total) run()
        })
    }

    for(let i = 0;i<limit;i++){
        run()
    }
    

}
limtPromise(fns,2)

深度优先遍历(DFS)


 function( node ){
    let stack = []
    let nodes = []
    if (node) {
        stack.push(node)
        while (stack.length) {
        	//每次取最后一个
            let item = stack.pop()
            let children = item.children || []
            nodes.push(item)
            //判断children的长度
            for (let i = children.length - 1; i >= 0; i--) {
                stack.push(children[i])
            }
        }
    }
    return nodes
 }

树的递归

     function dfs( root,result = [] ){
            if(!root){
                return 
            }
           root // result.push(root.val) 先序
           dfs(root.left,result) //  result.push(root.val) 中序
          dfs(root.right,result) //  result.push(root.val) 后序

     }


广度优先遍历(BFS)


 function bfs( node ){
    let nodes = []
    let queue = []
    if (node) {
        queue.push(node)
        while (queue.length) {
        	//取第一个
            let item = queue.shift()
            let children = item.children || []
            nodes.push(item)
            for (let i = 0; i < children.length; i++) {
                queue.push(children[i])
            }
        }
    }
    return nodes

 }

先序遍历(pre)

 function pre( root ){
    let nodes = []
    if(!root){
       return []
    }
    let stack = [root]
    let result = []
    while (stack.length) {
        const node =  stack.pop()
        result.push(node.val)
        if(root.right){
            stack.push(root.right)
        }
        if(root.left){
            stack.push(root.left)
        }
        
    }
    return nodes
 }

后序遍历(last)

 function last( root ){
    let nodes = []
    if(!root){
       return []
    }
    let stack = [root]
    let result = []
    while (stack.length) {
        const node = stack.pop()
        result.unshift(node.val)
        
        if(root.left){
            stack.push(root.left)
        }
         if(root.right){
            stack.push(root.right)
        }
        
    }
    return nodes
 }

中序遍历(mid)

 function mid( root ){
    let nodes = []
    if(!root){
       return []
    }
    let stack = []
    while(root || stack.length){
        while(root){
            stack.push(root)
            root = root.left
        }
        const node = stack.pop()
        nodes.push(node.val)
        root = node.right
    }
   
    return nodes
 }
 
 const bt = {
    val: 56,
    left: {
      val: 22,
      left: {
        val: 10,
        left: null,
        right: null,
      },
      right: {
        val: 30,
        left: null,
        right: null,
      },
    },
    right: {
      val: 81,
      left: {
        val: 77,
        left: null,
        right: null,
      },
      right: {
        val: 92,
        left: null,
        right: null,
      },
    },
  };
 
  mid(bt) //  10  22 30 56  77 81 92

Promise.resolve(1) .then(()=>{ return 2 }).then(console.log)