hi,你好!欢迎访问本站!登录
本站由网站地图腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - 教程 - 前端开发 - 正文 君子好学,自强不息!

JavaScript罕见的手写功用_WEB前端开发

2020-09-19前端开发搜奇网55°c
A+ A-

相干进修引荐:javascript

1. 防抖

function debounce(func, ms = 500) {  let timer;  return function (...args) {    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      func.apply(this, args);
    }, ms);
  };
}复制代码

2. 撙节

function throttle(func, ms) {  let canRun = true;  return function (...args) {    if (!canRun) return;
    canRun = false;
    setTimeout(() => {
      func.apply(this, args);
      canRun = true;
    }, ms);
  };
}复制代码

3. new

function myNew(Func) {  const instance = {};  if (Func.prototype) {    Object.setPrototypeOf(instance, Func.prototype);
  }  const res = Func.apply(instance, [].slice.call(arguments, 1));  if (typeof res === "function" || (typeof res === "object" && res !== null)) {    return res;
  }  return instance;
}复制代码

4. bind

Function.prototype.myBind = function (context = globalThis) {  const fn = this;  const args = Array.from(arguments).slice(1);  const newFunc = function () {    if (this instanceof newFunc) {      // 经由过程 new 挪用,绑定 this 为实例对象
      fn.apply(this, args);
    } else {      // 经由过程一般函数情势挪用,绑定 context
      fn.apply(context, args);
    }
  };  // 支撑 new 挪用体式格局
  newFunc.prototype = fn.prototype;  return newFunc;
};复制代码

5. call

Function.prototype.myCall = function (context = globalThis) {  // 症结步骤,在 context 上挪用要领,触发 this 绑定为 context
  context.fn = this;  let args = [].slice.call(arguments, 1);  let res = context.fn(...args);  delete context.fn;  return res;
};复制代码

6. apply

Function.prototype.myApply = function (context = globalThis) {  // 症结步骤,在 context 上挪用要领,触发 this 绑定为 context
  context.fn = this;  let res;  if (arguments[1]) {
    res = context.fn(...arguments[1]);
  } else {
    res = context.fn();
  }  delete context.fn;  return res;
};复制代码

7. deepCopy

function deepCopy(obj, cache = new WeakMap()) {  if (!obj instanceof Object) return obj;  // 防备轮回援用
  if (cache.get(obj)) return cache.get(obj);  // 支撑函数
  if (obj instanceof Function) {    return function () {
      obj.apply(this, arguments);
    };
  }  // 支撑日期
  if (obj instanceof Date) return new Date(obj);  // 支撑正则对象
  if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags);  // 还能够增添其他对象,比方:Map, Set等,依据状况推断增添即可,口试点到为止就能够了

  // 数组是 key 为数字素银的特别对象
  const res = Array.isArray(obj) ? [] : {};  // 缓存 copy 的对象,用于出来轮回援用的状况
  cache.set(obj, res);  Object.keys(obj).forEach((key) => {    if (obj[key] instanceof Object) {
      res[key] = deepCopy(obj[key], cache);
    } else {
      res[key] = obj[key];
    }
  });  return res;
}复制代码

8. 事宜总线 | 宣布定阅形式

class EventEmitter {  constructor() {    this.cache = {};
  }

  on(name, fn) {    if (this.cache[name]) {      this.cache[name].push(fn);
    } else {      this.cache[name] = [fn];
    }
  }

  off(name, fn) {    const tasks = this.cache[name];    if (tasks) {      const index = tasks.findIndex((f) => f === fn || f.callback === fn);      if (index >= 0) {
        tasks.splice(index, 1);
      }
    }
  }

  emit(name) {    if (this.cache[name]) {      for (let fn of this.cache[name]) {
        fn();
      }
    }
  }


  emit(name, once = false) {    if (this.cache[name]) {      // 建立事宜副本,假如回调函数内继续注册雷同事宜,触发时,会形成死轮回
      const tasks = this.cache[name].slice()      for (let fn of tasks) {
        fn();
      }      if (once) {        delete this.cache[name]
      }
    }
  }
}复制代码

9. 柯里化:只传递给函数一部分参数来挪用它,让它返回一个函数去处置惩罚剩下的参数

function curry(func) {  return function curried(...args) {    if (args.length >= func.length) {
      func.apply(this, args);
    } else {      return function (...args2) {
        curried.apply(this, args.concat(args2));
      };
    }
  };
}复制代码

10. es5 完成继续

function create(proto) {  function F() {}
  F.prototype = proto;  return new F();
}// Parentfunction Parent(name) {  this.name = name;
}

Parent.prototype.say = function () {  console.log(this.name);
};// Childfunction Child(age, name) {
  Parent.call(this, name);  this.age = age;
}
Child.prototype = create(Parent.prototype);
Child.prototype.constructor = Child;

Child.prototype.say = function () {  console.log(this.age);
};复制代码

11. instanceof

function instanceOf(instance, klass) {  let proto = instance.__proto__;  let prototype = klass.prototype;  while (true) {    if (proto === null) return false;    if (proto === prototype) return true;
    proto = proto.__proto__;
  }
}复制代码

12. 异步并发数限定

/**
 * 症结点申明
 * 1. new promise 一经建立,马上实行
 * 2. 运用 Promise.resolve().then 能够把使命加到微使命行列,防备马上实行迭代要领
 * 3. 微使命处置惩罚过程当中,发生的新的微使命,会在统一事宜轮回内,追加到微使命行列里
 * 4. 运用 race 在某个使命完成时,继续增加使命,坚持使命根据最大并发数举行实行
 * 5. 使命完成后,需要从 doingTasks 中移出
 */function limit(count, array, iterateFunc) {  const tasks = [];  const doingTasks = [];  let i = 0;  const enqueue = () => {    if (i === array.length) {      return Promise.resolve();
    }    const task = Promise.resolve().then(() => iterateFunc(array[i++]));
    tasks.push(task);    const doing = task.then(() => doingTasks.splice(doingTasks.indexOf(doing), 1));
    doingTasks.push(doing);    const res = doingTasks.length >= count ? Promise.race(doingTasks) : Promise.resolve();    return res.then(enqueue);
  };  return enqueue().then(() => Promise.all(tasks));
}// testconst timeout = i => new Promise(resolve => setTimeout(() => resolve(i), i));
limit(4, [1000, 1000, 1000, 1000], timeout).then((res) => {  console.log(res);
})复制代码

13. 异步串行 | 异步并行

// 大厂口试题,完成一个异步加法function asyncAdd(a, b, callback) {
  setTimeout(function () {
    callback(null, a + b);
  }, 1000);
}// 0. promisifyconst promiseAdd = (a, b) => new Promise((resolve, reject) => {
  asyncAdd(a, b, (err, res) => {    if (err) {
      reject(err)
    } else {
      resolve(res)
    }
  })
})// 1. 串行处置惩罚async function serialSum(...args) {  return args.reduce((task, now) => task.then(res => promiseAdd(res, now)), Promise.resolve(0))
}// 2. 并行处置惩罚async function parallelSum(...args) {  if (args.length === 1) return args[0]  const tasks = []  for (let i = 0; i < args.length; i += 2) {
    tasks.push(promiseAdd(args[i], args[i + 1] || 0))
  }  const results = await Promise.all(tasks)  return parallelSum(...results)
}// 测试(async () => {  const res1 = await serialSum(1, 2, 3, 4, 5, 8, 9, 10, 11, 12)  console.log(res1)  const res2 = await parallelSum(1, 2, 3, 4, 5, 8, 9, 10, 11, 12)  console.log(res2)
})()复制代码

14. vue reactive

// Dep moduleclass Dep {  static stack = []  static target = null
  deps = null
  
  constructor() {    this.deps = new Set()
  }

  depend() {    if (Dep.target) {      this.deps.add(Dep.target)
    }
  }

  notify() {    this.deps.forEach(w => w.update())
  }  static pushTarget(t) {    if (this.target) {      this.stack.push(this.target)
    }    this.target = t
  }  static popTarget() {    this.target = this.stack.pop()
  }
}// reactivefunction reactive(o) {  if (o && typeof o === 'object') {    Object.keys(o).forEach(k => {
      defineReactive(o, k, o[k])
    })
  }  return o
}function defineReactive(obj, k, val) {  let dep = new Dep()  Object.defineProperty(obj, k, {
    get() {
      dep.depend()      return val
    },
    set(newVal) {
      val = newVal
      dep.notify()
    }
  })  if (isObj(val)) {
    reactive(val)
  }
}// watcherclass Watcher {  constructor(effect) {    this.effect = effect    this.update()
  }

  update() {
    Dep.pushTarget(this)    this.value = this.effect()
    Dep.popTarget()    return this.value
  }
}// 测试代码const data = reactive({  msg: 'aaa'})new Watcher(() => {  console.log('===> effect', data.msg);
})

setTimeout(() => {
  data.msg = 'hello'}, 1000)复制代码

15. promise

// 发起浏览 [Promises/A+ 规范](https://promisesaplus.com/)class MyPromise {  constructor(func) {    this.status = 'pending'
    this.value = null
    this.resolvedTasks = []    this.rejectedTasks = []    this._resolve = this._resolve.bind(this)    this._reject = this._reject.bind(this)    try {
      func(this._resolve, this._reject)
    } catch (error) {      this._reject(error)
    }
  }

  _resolve(value) {
    setTimeout(() => {      this.status = 'fulfilled'
      this.value = value      this.resolvedTasks.forEach(t => t(value))
    })
  }

  _reject(reason) {
    setTimeout(() => {      this.status = 'reject'
      this.value = reason      this.rejectedTasks.forEach(t => t(reason))
    })
  }

  then(onFulfilled, onRejected) {    return new MyPromise((resolve, reject) => {      this.resolvedTasks.push((value) => {        try {          const res = onFulfilled(value)          if (res instanceof MyPromise) {
            res.then(resolve, reject)
          } else {
            resolve(res)
          }
        } catch (error) {
          reject(error)
        }
      })      this.rejectedTasks.push((value) => {        try {          const res = onRejected(value)          if (res instanceof MyPromise) {
            res.then(resolve, reject)
          } else {
            reject(res)
          }
        } catch (error) {
          reject(error)
        }
      })
    })
  }  catch(onRejected) {    return this.then(null, onRejected);
  }
}// 测试new MyPromise((resolve) => {
  setTimeout(() => {
    resolve(1);
  }, 500);
})
  .then((res) => {    console.log(res);    return new MyPromise((resolve) => {
      setTimeout(() => {
        resolve(2);
      }, 500);
    });
  })
  .then((res) => {    console.log(res);
  }, err => {    console.log('==>', err);
  });复制代码

迎接人人一同补充~

以上就是JavaScript罕见的手写功用的细致内容,更多请关注ki4网别的相干文章!

  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  移步手机端
JavaScript罕见的手写功用_WEB前端开发

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章
标签:

本文来源:搜奇网

本文地址:https://www.sou7.cn/300793.html

关注我们:微信搜索“搜奇网”添加我为好友

版权声明: 本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。请记住本站网址https://www.sou7.cn/搜奇网。