JavaScript的「手写」知识点,扫盲啦!


JavaScript的「手写」知识点

1、实现原生 AJAX 封装

const ajax = {
  get(url, fn) {
    const xhr = new XMLHttpRequest()
    xhr.open('GET', url, true)
    xhr.onreadystatechange = function() {
      if(xhr.readyState === 4) {
        fn(xhr.responseText)
      }
    }
    xhr.send()
  },
  post(url, fn, data) {
    const xhr = new XMLHttpRequest()
    xhr.open('POST', url, true)
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
    xhr.onreadystatechange = function() {
      if(xhr.readyState === 4) {
        fn(xhr.responseText)
      }
    }
    xhr.send(data)
  }
}

2、实现 new 过程

function myNew(fn, ...args) {
    const obj = {}

    obj.__proto__ = fn.prototype

    fn.apply(obj, args)

    return obj
}

3、打乱一个数组

// 方法1
const shuffle = (arr) => {
  return arr.sort(() => {
    return Math.random() > 0.5 ? 1 : -1
  })
}

// 方法2
const shuffle = (arr) => { 
    let i = arr.length
    while (i) { 
        let j = Math.floor(Math.random() * i--)
        [arr[j], arr[i]] = [arr[i], arr[j]]
    } 
}

4、防抖函数

function debounce(fn, delay = 200) {
  let timer
  return function(...args) {
    if (timer) {
      clearTimeout(timer)
      timer = null
    }
    timer = setTimeout(() => {
      fn.apply(this, args)
      clearTimeout(timer)
      timer = null
    }, delay)
  }
}

5、节流函数

function throttle(fn, delay = 200) {
  let flag = true
  return function(...args) {
    if(!flag) {
      return
    }
    flag = false
    let timer = setTimeout(() => {
      fn.apply(this, args)
      flag = true
      clearTimeout(timer)
    }, delay)
  }
}

6、数组去重

// 方法1
const quchong = (arr) => {
  return [...new Set(arr)]
}

// 方法2
const quchong = (arr) => {
  const res = []
  arr.reduce((pre, next) => {
    if (!pre.has(next)) {
      pre.set(next, 1)
      res.push(next)
    }
    return pre
  }, new Map())

  return res
}

7、setTimeout 实现 setInterval

const mySetInterval = (fn, delay) => {
  let timer = null
  const interval = () => {
    fn()
    timer = setTimeout(interval, delay)
  }
  timer = setTimeout(interval, delay)

  return {
    cancel: () => {
      clearTimeout(timer)
    }
  }
}

8、setInterval 实现 setTimeout

const mySetTimeout = (fn, delay) => {
  const timer = setInterval(() => {
    fn()
    clearInterval(timer)
  }, delay)
}

9、compose 函数

function fn1(x) {
  return x + 1;
}

function fn2(x) {
  return x + 2;
}

function fn3(x) {
  return x + 3;
}

function fn4(x) {
  return x + 4;
}
const compose = (...fns) => {
  if (fns.length === 0) return (num) => num
  if (fns.length === 1) return fns[0]
  return fns.reduce((pre, next) => {
    return (num) => {
      return pre(next(num))
    }
  })
}
const a = compose(fn1, fn2, fn3, fn4)
console.log(a(1)); // 1+2+3+4=11

10、curring 函数

const add = (a, b, c) => a + b + c;
const currying = (fn, ...args) => {
  let allArgs = [...args]
  const num = fn.length
  const res = (...args2) => {
    allArgs = [...allArgs, ...args2]
    if (allArgs.length === num) {
      return fn(...allArgs)
    } else {
      return res
    }
  }
  return res
}
const a = currying(add, 1);
console.log(a(2)(3)) // 1 + 2 + 3=6

11、LRU 算法

class LRUCache {
  constructor(size) {
    this.size = size
    this.cache = new Map()
  }
  get(key) {
    const hasKey = this.cache.has(key)
    if (!hasKey) {
      return -1
    } else {
      const val = this.cache.get(key)
      this.cache.delete(key)
      this.cache.set(key, val)
      return val
    }
  }
  put(key, value) {
    const hasKey = this.cache.has(key)
    if (hasKey) {
      this.cache.delete(key)
    }
    this.cache.set(key, value)
    if (this.cache.size > this.size) {
      this.cache.delete(this.cache.keys().next().value)
    }
  }
}

12、发布订阅模式

class EventEmitter {
  constructor() {
    this.cache = []
  }

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

  off(name, fn) {
    if (!name) {
      this.cache = []
      return
    }
    const tasks = this.cache[name]
    if (tasks) {
      if (!fn) {
        this.cache[name] = []
      }
      const index = tasks.findIndex(item => item === fn)
      if (index >= 0) {
        tasks.splice(index, 1)
      }
    }
  }

  emit(name, ...args) {
    // 复制一份。防止回调里继续on,导致死循环
    const tasks = this.cache[name].slice()
    if (tasks) {
      for (let task of tasks) {
        task(...args)
      }
    }
  }

  once(name, cb) {
    const fn = (...args) => {
      cb(...args)
      this.off(name, fn)
    }
    this.on(name, fn)
  }
}

13、DOM 转 对象

const dom2tree = (node) => {
  const obj = {}
  obj.tag = node.tagName
  obj.children = []
  node.childNodes.forEach(child => obj.children.push(dom2tree(child)))
  return obj
}

14、对象 转 DOM

function _render(vnode) {
  if (typeof vnode === 'number') {
    vnode = String(vnode)
  }

  if (typeof vnode === 'string') {
    return document.createTextNode(vnode)
  }

  const dom = document.createElement(vnode.tag)
  if (vnode.attrs) {
    Object.keys(attrs).forEach(key => {
      const attr = artts[key]
      dom.setAttribute(key, attr)
    })
  }
  vnode.children.forEach(child => dom.appenChild(_render(child)))

  return dom
}

15、判断对象环引用

const cycleDetector = (obj) => {
  const arr = [obj]
  let flag = false

  const cycle = (o) => {
    const values = Object.values(o)
    for (let value of values) {
      if (typeof value === 'object' && value !== null) {
        if (arr.includes(value)) {
          flag = true
          return
        }
        arr.push(value)
        cycle(value)
      }
    }
  }

  cycle(obj)

  return flag
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骆骆爱学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值