1、防抖

防抖限制多长时间执行一次,节流限制多长时间必须执行依次
适用范围 input框实时搜索 防抖
debounce限制多长时间才能执行一次,throttle限制多长时间必须执行一次,一个限制上限、一个限制下限

  1. function debounce(func, delay) {
  2. let timeout = null;.//闭包
  3. return function(e) {
  4. if(timeout){
  5. clearTimeout(timeout)
  6. }
  7. var context = this, args = arguments
  8. timeout = setTimeout(function(){
  9. func.apply(context, args);
  10. },delay)
  11. };
  12. };
  13. // 测试
  14. function task() {
  15. console.log('run task')
  16. }
  17. const debounceTask = debounce(task, 1000)
  18. window.addEventListener('scroll', debounceTask)

2、节流

适用范围在 比input, keyup更频繁触发的事件中,如resize, touchmove, mousemove, scroll。throttle 会强制函数以固定的速率执行。因此这个方法比较适合应用于动画相关的场景。

  1. throttle(fn,delay){
  2. let valid = true
  3. return function() {
  4. if(!valid){
  5. return false
  6. }
  7. var context = this, args = arguments
  8. valid = false
  9. setTimeout(() => {
  10. fn.apply(context, args)
  11. valid = true;
  12. }, delay)
  13. }
  14. }
  15. /////
  16. function throttle(fn, delay) {
  17. let last = 0 // 上次触发时间
  18. return (...args) => {
  19. const now = Date.now()
  20. if (now - last > delay) {
  21. last = now
  22. fn.apply(this, args)
  23. }
  24. }
  25. }
  26. // 测试
  27. function task() {
  28. console.log('run task')
  29. }
  30. const throttleTask = throttle(task, 1000)
  31. window.addEventListener('scroll', throttleTask)

3、深拷贝

  1. function deeepClone(obj, cache = new WeakMap()) {
  2. if (typeof obj !== 'object') return obj
  3. if (obj === null) return obj
  4. if (cache.get(obj)) return cache.get(obj) // 防止循环引用,程序进入死循环
  5. if (obj instanceof Date) return new Date(obj)
  6. if (obj instanceof RegExp) return new RegExp(obj)
  7. // 找到所属原型上的constructor,所属原型上的constructor指向当前对象的构造函数
  8. let cloneObj = new obj.constructor()
  9. cache.set(obj, cloneObj) // 缓存拷贝的对象,用于处理循环引用的情况
  10. for (let key in obj) {
  11. if (obj.hasOwnProperty(key)) {
  12. cloneObj[key] = deepClone(obj[key], cache) // 递归拷贝
  13. }
  14. }
  15. return cloneObj
  16. }
  17. const obj = { name: 'Jack', address: {x: 100, y: 200}}
  18. obj.a = obj
  19. const newObj = deepClone(obj)
  20. console.log(newObj.address === obj.address)

4、Promise

  1. class MyPromise {
  2. constructor(executor) { // executor执行器
  3. this.status = 'pending' // 等待状态
  4. this.value = null // 成功或失败的参数
  5. this.fulfilledCallbacks = [] // 成功的函数队列
  6. this.rejectedCallbacks = [] // 失败的函数队列
  7. const that = this
  8. function resolve(value) { // 成功的方法
  9. if (that.status === 'pending') {
  10. that.status = 'resolved'
  11. that.value = value
  12. that.fulfilledCallbacks.forEach(myFn => myFn(that.value)) //执行回调方法
  13. }
  14. }
  15. function reject(value) { //失败的方法
  16. if (that.status === 'pending') {
  17. that.status = 'rejected'
  18. that.value = value
  19. that.rejectedCallbacks.forEach(myFn => myFn(that.value)) //执行回调方法
  20. }
  21. }
  22. try {
  23. executor(resolve, reject)
  24. } catch (err) {
  25. reject(err)
  26. }
  27. }
  28. then(onFulfilled, onRejected) {
  29. if (this.status === 'pending') {
  30. // 等待状态,添加回调函数到成功的函数队列
  31. this.fulfilledCallbacks.push(() => {
  32. onFulfilled(this.value)
  33. })
  34. // 等待状态,添加回调函数到失败的函数队列
  35. this.rejectedCallbacks.push(() => {
  36. onRejected(this.value)
  37. })
  38. }
  39. if (this.status === 'resolved') { // 支持同步调用
  40. console.log('this', this)
  41. onFulfilled(this.value)
  42. }
  43. if (this.status === 'rejected') { // 支持同步调用
  44. onRejected(this.value)
  45. }
  46. }
  47. }
  48. // 测试
  49. function fn() {
  50. return new MyPromise((resolve, reject) => {
  51. setTimeout(() => {
  52. if(Math.random() > 0.6) {
  53. resolve(1)
  54. } else {
  55. reject(2)
  56. }
  57. }, 1000)
  58. })
  59. }
  60. fn().then(
  61. res => {
  62. console.log('res', res) // res 1
  63. },
  64. err => {
  65. console.log('err', err) // err 2
  66. })

5、异步控制并发数

  1. function limitRequest(urls, limit){
  2. return new Promise((resolve, reject)=>{
  3. const len = urls.length
  4. let count = 0
  5. // 同时启动多个limit 数量的任务
  6. while(limit > 0){
  7. start()
  8. limit -= 1
  9. }
  10. function start(){
  11. const url = urls.shift()
  12. if(url) {
  13. axios.post(url).finally(()=>{
  14. if(count == len - 1){
  15. //完成最后一个任务
  16. resolve()
  17. }else {
  18. // 完成本任务 执行下一个任务
  19. count++
  20. start()
  21. }
  22. })
  23. }
  24. }
  25. })
  26. }
  27. limitRequest(urls, limit)
  28. // 可以批量请求数据,所有的URL地址在urls参数中
  29. // 同时可以通过max参数 控制请求的并发度
  30. // 当所有的请求结束后,需要执行callback回调
  31. function sendRequest(urls, max ,callback){
  32. if(!urls ||!max) return
  33. if(urls.length === 0 ){
  34. if(callback) callback()
  35. return
  36. }
  37. let fetchArr = [],
  38. i =0;
  39. function toFetch(){
  40. if(i === urls.length ) return Promise.resolve()
  41. // 取出第i个url 放进fetch里面
  42. let one = fetch(urls[i++])
  43. // 存入并发数组
  44. fetchArr.push(one)
  45. // 执行完从并发数组删除
  46. one.then(res => {
  47. console.log(res)
  48. fetchArr.splice(fetchArr.indexOf(one), 1)
  49. })
  50. let p = Promise.resolve()
  51. // 当并行数量到达限制后 使用race 比较 第一个完成。然后在调用函数本身
  52. if(fetchArr.length >= max) p = Promise.race(fetchArr)
  53. return p.then(() => toFetch())
  54. }
  55. // 循环完数组,使用all 等待全部执行完后调用回调函数
  56. toFetch()
  57. .then(()=> Promise.all(fetchArr))
  58. .then(()=> callback())
  59. }
  60. sendRequest(urls, max, callback)

6、寄生组合继承

  1. function Parent(name) {
  2. this.name = name
  3. }
  4. Parent.prototype.eat = function() {
  5. console.log(this.name + 'is eating');
  6. }
  7. function Child (name, age) {
  8. Parent.call(this, name)
  9. this.age = age
  10. }
  11. Child.prototype = Object.create(Parent.prototype)
  12. Child.prototype.constructor = Child
  13. Child.prototype.study = function() {
  14. console.log(this.name + "is studying");
  15. }
  16. let child = new Child('xiaoxiao', 16)
  17. console.log(child.name)
  18. child.eat()
  19. child.study()

7、排序

sort 排序

  1. // 对数字排序
  2. const arr =[2,1]
  3. arr.sort((a,b) => a-b)
  4. // 对字母排序
  5. const arr = ['b', 'c', 'a', 'e', 'd']
  6. arr.sort()

冒泡排序

  1. function bubbleSort(arr) {
  2. let len = arr.length
  3. for (let i = 0; i < len - 1; i++) {
  4. // 从第一个元素开始,比较相邻的两个元素,前者大就交换位置
  5. for (let j = 0; j < len - 1 - i; j++) {
  6. if (arr[j] > arr[j + 1]) {
  7. let num = arr[j]
  8. arr[j] = arr[j + 1]
  9. arr[j + 1] = num
  10. }
  11. }
  12. // 每次遍历结束,都能找到一个最大值,放在数组最后
  13. }
  14. return arr
  15. }
  16. //测试
  17. console.log(bubbleSort([2, 3, 1, 5, 4])) // [1, 2, 3, 4, 5]

8、去重

  1. //set去重
  2. cosnt newArr = [...new Set(arr)]
  3. //Array.from 去重
  4. const newArr = Array.from(new Set(arr))
  5. //indexOf 去重
  6. function re(arr) {
  7. let num = []
  8. arr.forEach((item)=>{
  9. if(res.indexOf(item) === -1){
  10. res.push(item)
  11. }
  12. })
  13. return num
  14. }

9、url参数

  1. URLSearchParams
  2. // 创建一个URLSearchParams实例
  3. const urlSearchParams = new URLSearchParams(window.location.search);
  4. // 把键值对列表转换为一个对象
  5. const params = Object.fromEntries(urlSearchParams.entries());
  6. function getParams(url) {
  7. const res = {}
  8. if(url.includes('?')) {
  9. const str = url.split('?')[1]
  10. const arr = str.split('&')
  11. arr.forEach(item => {
  12. const key = item.split('=')[0]
  13. const val = item.split('=')[1]
  14. res[key] = decodeURIComponent(val) //解码
  15. });
  16. }
  17. return res
  18. }
  19. const user = getParams('http://www.baidu.com?user=%E9%98%BF%E9%A3%9E&age=16')
  20. console.log(user) // { user: '阿飞', age: '16' }

10、发布者/订阅者

  1. // 发布者订阅者模式
  2. class EventEmitter {
  3. constructor() {
  4. this.subs = Object.create(null)
  5. }
  6. // 订阅
  7. $on(eventType,handler) {
  8. this.subs[eventType] = this.subs[eventType] || []
  9. this.subs[eventType].push(handler)
  10. }
  11. // 发布
  12. $emit(eventType) {
  13. console.log(this.subs, 'subs')
  14. console.log(this.subs[eventType], 'event')
  15. if(this.subs[eventType]){
  16. this.subs[eventType].forEach(func => {
  17. func()
  18. });
  19. }
  20. }
  21. }
  22. let em =new EventEmitter();
  23. em.$on('event', () => {
  24. console.log('1号订阅')
  25. })
  26. em.$on('event', () => {
  27. console.log('2号也订阅')
  28. })
  29. setTimeout(()=>{
  30. em.$emit('event')
  31. },3000)