js 手写

154 阅读2分钟

深拷贝

const deepClone = para => {
  if(!para || typeof para !== 'object') return fasle
  const temp = Array.isArray(para) ? [] : {}
  for (const key in para) {
    if (Object.hasOwnProperty.call(para, key)) {
      const value = para[key];
      temp[key] = typeof value === 'object' ? deepClone(value) : value
    }
  }
  return temp
}

路由参数

const parseUrlString = url => {
  const newurl = url 
  if(!newurl) newurl = window.location.search
   const arr = newurl.split('?')
   if(arr.length < 2) return  false
   return arr[1].split('&').reduce((pre,cur) => {
     const temp = cur.split('=')
     pre[temp[0]]=temp[1]
     return pre
   },{})
}

原型

function Animal () {
  this.type = '动物';
}

Animal.prototype.type = '哺乳类';

let cat = new Animal();

console.log(cat.__proto__ === Animal.prototype); // true
console.log(cat.constructor==Animal,99); 

call

const mycall = function(obj=window, ...arr){
   const fn = Symbol()
   obj[fn] = this
   const res = obj[fn](...arr)
   delete obj[fn]
   return res
}

bind

const mybind = function(obj = window, ...arr1){
   let that = this 
   let fn = function(){}
   fn.prototype = that.prototype
  let func = function(...arr2){
    const _self = this instanceof func ? this :obj
   return  that.call(_self,...arr1,...arr2)
  }
  func.prototype = new fn()
  return func
}

map

Array.prototype.myMap = function(fn){
  if(typeof fn !== 'function') return false
  const array  = this 
  const resarr = []
 for (let index = 0; index < array.length; index++) {
  resarr[index] = fn(array[index],index,array)
 }
 return resarr
}

instanceof

function myInstanceof(left,right){
  if(!['object','Function'].includes(typeof left) || left ===null) return false
  let le = left.__proto__
  let ri = right.prototype
  while(true){
    if (le===ri) return true
      le = le.__proto__
  }
}

flat

function flatten(arr){
    if(Array.isArray(arr)){
      return arr.reduce((pre,cue)=>{
        return pre.concat(Array.isArray(cue)?flat(cue) : cue)
      },[])
    }
}
function flatten(arr) {
   return arr.toString().split(',').map(item=>{
     return +item
   })
}

new

function mynew(fn) {
  const obj = {}
  obj.__proto__ = fn.prototype
  fn.call(obj)
  return obj
}

create

function create(proto) {
  function F() {};
  F.prototype = proto;
  F.prototype.constructor = F;
  return new F();
}

reduce

Array.prototype.myreduce=function(fn,initVal) {
  if(typeof fn !== "function") return new Error("传入函数")
  const arr = this 
  const start = initVal ? 0 : 1
  let pre = initVal ? initVal : arr[0]
  for (let index = start; index < arr.length; index++) {
      pre = fn(pre ,arr[index],index,arr)
  }
  return pre
}

发布订阅

class PubSub{
  constructor(){
      this.obj = {}
  }
  on(type, fn){
      this.obj[type] =  this.obj[type] || []
      this.obj[type].push(fn)
  }
  emit(type, data){
      this.obj[type] = this.obj[type] || []
      this.obj[type].forEach(fn => {
          fn(data)
      });
  }
  off(type,fn){
      if (!this.obj[type]) return;
      this.obj[type] = this.obj[type].filter((item) => {
        return item !== fn;
      });
    }
    once(type,fun){
      
    }
}

节流

/**

  • 节流:滚动加载更多、搜索框搜的索联想功能、高频点击、表单重复提交……
  • 节流函数 一个函数执行一次后,只有大于设定的执行周期才会执行第二次。有个需要频繁触发的函数,出于优化性能的角度,在规定时间内,只让函数触发的第一次生效,后面的不生效。
  • @param fn要被节流的函数
  • @param delay规定的时间 */
 function throttle(fn, delay) {
  var lastTime = 0;
  return function(){
      var nowTime = Date.now();
      if(nowTime - lastTime > delay){
          fn()
          lastTime = nowTime;
      }
  }
}

防抖

/**

  • 防抖:搜索框搜索输入,并在输入完以后自动搜索、手机号,邮箱验证输入检测、窗口大小 resize 变化后,再重新渲染。
  • 防抖函数 一个需要频繁触发的函数,在规定时间内,只让最后一次生效,前面的不生效
  • @param fn要被节流的函数
  • @param delay规定的时间 */
 function debounce(fn, delay) {
  let timer = null;
  return function () {
      timer && clearTimeout(timer)
      timer = setTimeout(function(){
          fn()
      }, delay)
  }
}

promise

class myPromise {
  // promise有三种状态:  static来创建静态属性 分别是pending,fulfilled和rejected
  static PENDING = 'pending';
  static FULFILLED = 'fulfilled';
  static REJECTED = 'rejected';
  constructor(func) {
       // this.PromiseState 来保存实例的状态属性,这个状态属性默认就是 待定pending 状态,
      this.PromiseState = myPromise.PENDING;
      // 执行resolve()或者reject()可以传一个参 命名为PromiseResult
      this.PromiseResult = null;
      // 需要用bind 改编this指向
      func(this.resolve.bind(this), this.reject.bind(this));
  }
  resolve(result) {
      if (this.PromiseState === myPromise.PENDING) {
          this.PromiseState = myPromise.FULFILLED;
          this.PromiseResult = result;
      }
  }
  reject(reason) {
      if (this.PromiseState === myPromise.PENDING) {
          this.PromiseState = myPromise.REJECTED;
          this.PromiseResult = reason;
      }
  }
  then(onFulfilled,onRejected){
      onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
      onRejected = typeof onRejected === 'function' ? onRejected : reason => {
          throw reason;
      };
      
      if (this.PromiseState===Mypromise.FULFILLED) {
        onFulfilled( this.PromiseResult)
      }
      if (this.PromiseState===Mypromise.REJECTED) {
        onRejected( this.PromiseResult)
      }
    }
}