乐趣区

关于javascript:手写题整理

  • 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)

主动重试

退出移动版