手写题整理

  • promise
  • async await
  • 防抖,节流
  • 柯里化
  • 实现new,call, apply, bind
  • lazyman
  • flatten 数组扁平化
  • 发布订阅
  • 斐波那契数列生成
  • 错误重传封装

promise

promise实现

async await


function async(genF){
    function spawn(genF) {
      return new Promise(function(resolve, reject) {
        const gen = genF();
        function step(nextF) {
          let next;
          try {
            next = nextF();
          } catch(e) {
            return reject(e);
          }
          if(next.done) {
            return resolve(next.value);
          }
          Promise.resolve(next.value).then(function(v) {
            step(function() { return gen.next(v); });
          }, function(e) {
            step(function() { return gen.throw(e); });
          });
        }
        step(function() { return gen.next(undefined); });
      });
    }
    
    return spawn(genF);
}

防抖,节流

防抖:特定时间间隔之内不触发时调用
节流:特定时间间隔之内调用一次

// 防抖 特定时间间隔内不触发时才执行
function debounce(func, duration){
    let timer;

    return function(){
        const context = this;
        const args = [...arguments];

        if(timer){
            clearTimeout(timer);
            timer = null;
        }

        timer = setTimeout(function(){
            func.apply(context, args);
        }, duration);

    }
};

// 节流  特定时间间隔内只发生一次
function throttle(func, duration){
    let timer;

    return function(){
        const context = this;
        const args = [...arguments];

        if(timer){
            return;
        }

        timer = setTimeout(function(){
            func.apply(context, args);

            clearTimeout(timer);
            timer = null;

        }, duration);
    }
}

柯里化

在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
在直觉上,柯里化声称“如果你固定某些参数,你将得到接受余下参数的一个函数”。

说人话就是把接受多个参数的函数转为多个嵌套的单个参数的函数。我们使用场景的职责链模式是柯里化的例子,每个函数只处理自己关心的参数。

柯里化的好处:

  1. 参数复用:一些固定参数不用重复传,比如类型校验函数。
  2. 延迟调用:bind函数
  3. 提前返回: 如对DOM事件封装等,自执行函数中提前返回一个函数。下次不用做重复判断了。
// 柯里化
function currying(fn){
    // 函数的参数个数
    const max = fn.length;
    let arr = [];

    const closure = function(...args){
        arr = arr.concat(args);

        // 没调用完,返回函数
        if(arr.length < max){
            return closure;
        }else{
            return fn(...arr);
        }
    };

    return closure;
}

function add(x, y, z) {
  return x + y + z
}

curriedAdd = currying(add)
console.log('柯里化', curriedAdd(1, 2)(3));

实现new, call, apply, bind


// call
Function.prototype.callFunc = function callFunc(){
    const self = [...arguments][0];
    const args = [...arguments].slice(1);

    self.fn = this;

    const res = self.fn(...args);

    delete self.fn;

    return res;
}

// apply
Function.prototype.applyFunc = function applyFunc(){
    const self = [...arguments][0];
    const args = [...arguments][1];

    self.fn = this;

    const res = self.fn(...args);

    delete self.fn;

    return res;
}

// bind
Function.prototype.bind = function(){
    let self = this;
    let context = [...arguments][0];
    let args = [...arguments].slice(1);

    return function(){
        return self.apply(context, [...args, ...arguments])
    }
};

var getVal = function(z, m){
    return this.val + this.y + z + m;
}


console.log(getVal.callFunc({
    val: 456,
    y: 123
},4,5));


console.log(getVal.applyFunc({
    val: 456,
    y: 123
}, [4,5]))
// 实现 new
function Create(Con, arguments){

    const Con = [...arguments][0];
    const args = [...arguments].slice(1);
    // 创建一个新对象
    const obj = {};

    // 指定原型
    obj.setPropertyOf(Con.prototype);

    // 执行构造函数
    const res = Con.call(obj, ...args);

    // 返回对象
    return typeof res === 'object' ? res : obj;
}

lazyman

flatten 数组扁平化

// 数组扁平化
function flatten(arr = []){
    if(!arr.length){
        return arr;
    }

    let res = [];

    arr.forEach((item, index) => {
        if(!Array.isArray(item)){
            res.push(item);
        }else{
            res = res.concat(flatten(item));
        }
    });
    
    return res;
}

发布订阅

[发布]

斐波那契数列生成

// 斐波那契数列
function fibonacci(n){
    const arr = [0 ,1];
    let a = 0;
    let b = 1;

    while(arr.length < n){
        [a, b] = [b, a + b];

        arr.push(b);
    }
    return arr;
}

console.log('斐波那契数列', fibonacci(8));

错误重传封装

// 重传
function retry(promiseFn, times = 3, duration = 200){
    return new Promise((resolve, reject) => {
        const handler = () => {
            promiseFn().then(res => resolve(res)).catch(err => {
                times--;

                if(!times){
                    reject(err);
                }else{
                    setTimeout(handler, duration);
                }
            });
        };

        handler();

    });
}

function fetchData() {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
        console.log('server unavailable')
      reject('server unavailable');
    }, 500);
  });

}

retry(fetchData)

自动重试

你可能感兴趣的:(javascript前端)