likes
comments
collection
share

手动实现new, call, apply, bind,深浅拷贝,防抖,节流,Promise.all()

作者站长头像
站长
· 阅读数 67

new的实现

function Otaku (name, age) {
    this.name = name;
    this.age = age;

    this.habit = 'Games';
}
Otaku.prototype.strength = 60;

Otaku.prototype.sayYourName = function () {
    console.log('I am ' + this.name);
}
  function new1(){
    var obj = {};
    var Constructor = [].shift.call(arguments);
    obj.__proto__ = Constructor.prototype;
    var ret = Constructor.apply(obj,arguments);
    return typeof ret === 'object' ? ret : obj;
  }
  //测试
var a = new1(Otaku,'Kevin',18)
a.sayYourName();  //I am Kevin
console.log(a.name) //Kevin
console.log(a.age)  //18
console.log(a.habit)  //Games
console.log(a.strength) //60

call的实现

var value = 2;

var obj = {
    value: 1
}

function bar(name, age) {
    console.log(this.value);
    return {
        value: this.value,
        name: name,
        age: age
    }
}
Function.prototype.call2=function(context){
    var context = context || window;
    var args = [...arguments].slice(1);
    var result = null;
    context.fn=this;
    result = context.fn(...args);
    delete context.fn;
    return result;
 }
 //测试
bar.call(null); //2
console.log(bar.call2(obj, 'kevin', 18));
// 1
// Object {
//    value: 1,
//    name: 'kevin',
//    age: 18
// }

apply的实现

Function.prototype.apply2=function(context,arr){
    var context = context || window;
        context.fn = this;
    var result = null;
    if(!arr){
      result = context.fn();
    } else{
   result = context.fn(...arr);
    }
    delete context.fn;
    return result;
 }
 var value = 2;

var obj = {
    value: 1
}

function bar(name, age) {
    console.log(this.value);
    return {
        value: this.value,
        name: name,
        age: age
    }
}
//测试
bar.apply2(null); //2
console.log(bar.apply2(obj, ['kevin', 18]));
// 1
// Object {
//    value: 1,
//    name: 'kevin',
//    age: 18
// }

bind的实现

Function.prototype.bind2 = function(context){
     if(typeof this !== 'function'){
       throw new Error('this is not a function')
     }
     var args = Array.prototype.slice.call(arguments,1);
     var self = this;
     var FNOP = function(){};
     var fbound = function(){
       var bindArgs = Array.prototype.slice.call(arguments);
       return self.apply(this instanceof FNOP ? this:context, args.concat(bindArgs));
     }
     FNOP.prototype = self.prototype;
     fbound.prototype = new FNOP();
     return fbound;
   }

浅拷贝

function shallowCopy(obj){
    if(typeof obj !== 'object'){return}
    var newObj = obj instanceof Array ? [] : {};
    for(var key in obj){
        if(obj.hasOwnProperty(key)){
          newObj[key] = obj[key];
        }
    }
    return newObj;
  }

深拷贝

var deepCopy = function(obj){
   if(obj === null || typeof obj !== 'object'){return}
   var newObj = obj instanceof Array ? [] : {};
   for(var key in obj){
     if(obj.hasOwnProperty(key)){
       newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
     }
   }
   return newObj
 }

节流

节流有两种方式,一种是时间戳,一种是定时器

1、时间戳
// 在规定的时间间隔内只能执行一次事件处理函数,而不是像防抖,只有最后一次有效。
// 比如滚动页面,是每隔一个时间间隔就发松一次请求,而不是在最后停止滚动时才发送一次请求。
const throttle = function(fn, interval){
   let last = 0;
   return function (...args){
     let now = new Date();
     if(now - last < interval)return;
     last = now;
     fn.apply(this, args)
   }
 }
2、定时器
function throttle(fn, interval){
  let timer = null;
  return function(){
    let context = this;
    let args = [...arguments];
    if(!timer){
      let timer = setTimeout(function(){
        fn.apply(context, args);
        timer = null;
      }, interval)
    }
  }
}

防抖

// 不管事件处理函数触发了多少次,只有最后一次有效,在设定时间到达之前被触发,则重新延时。
const debounce = function(fn, delay){
   let timer = null;
   return function(...args){
     let context = this;
     if(timer){clearTimeout(timer)}
     timer = setTimeout(function(){
       fn.apply(context,args)
     },delay)
   }
 }

加强版节流

function throttle(fn, interval){
  let timer = null;
  let last = 0;
  return function(){
    let context = this;
    let args = [...arguments];
    let now = Date.now();
    if(now - last < interval){
      clearTimeout(timer);
      setTimeout(function(){
        last = now;
        fn.apply(context, args);
      }, interval)
    }else {
      last = now;
      fn.apply(context, args);
    }
  }
}

Promise.all实现

let MyPromiseAll = function(promises){
  let result = [];
  let promiseCount = 0;
  let promiseLen = promises.length;
  return new Promise(function(resolve,reject){
    for(let val of promises){
     Promise.resolve(val).then(function(res){
        result.push(val);
      promiseCount++;
      if(promiseCount === promiseLen){
        return resolve(result)
      }
     },function(err){
       throw reject(err)
     })
    }
  })
 }
转载自:https://juejin.cn/post/6844904106100785166
评论
请登录