1、Promise.all

Promise.myAll = function (promises) {
  return new Promise((resolve, reject) => {
    // promises 可以不是数组,但必须要具有 Iterator 接口
    if (typeof promises[Symbol.iterator] !== 'function') {
      reject('TypeError: promises is not iterable')
    }
    if (promises.length === 0) {
      resolve([])
    } else {
      const res = []
      const len = promises.length
      let count = 0
      for (let i = 0; i < len; i  ) {
        // Promise.resolve 的作用是将普通值或 thenable 对象转为 promise,promise 则直接返回
        Promise.resolve(promises[i])
          .then((data) => {
            res[i] = data
            count  = 1
            if (count === len) {
              resolve(res)
            }
          })
          .catch((err) => {
            reject(err)
          })
      }
    }
  })
}
// test
function p1() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 1)
  })
}
function p2() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 2)
  })
}
Promise.myAll([p1(), p2()]).then(res => {
  console.log(res) // [1, 2]
})

2、Promise.race

Promise.myRace = function (promises) {
  return new Promise((resolve, reject) => {
    // promises 可以不是数组,但必须要具有 Iterator 接口
    if (typeof promises[Symbol.iterator] !== 'function') {
      reject('TypeError: promises is not iterable')
    }
    for (const item of promises) {
      // 先出来的结果会被 resolve 或 reject 出去, 一旦状态变化就不会再变
      Promise.resolve(item).then(resolve, reject)
    }
  })
}
// test
function p1() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 1)
  })
}
function p2() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 2)
  })
}
Promise.myRace([p1(), p2()]).then((res) => {
  console.log(res) // 1
})

3、Promise.any

Promise.myAny = function (promises) {
  return new Promise((resolve, reject) => {
    // promises 可以不是数组,但必须要具有 Iterator 接口
    if (typeof promises[Symbol.iterator] !== 'function') {
      reject('TypeError: promises is not iterable')
    }
    const len = promises.length
    let count = 0
    for (let i = 0; i < len; i  ) {
      Promise.resolve(promises[i]).then(resolve, (err) => {
        count  = 1
        if (count === promises.length) {
          reject(new Error('所有 promise 都失败'))
        }
      })
    }
  })
}
// test
function p1() {
  return new Promise((resolve, reject) => {
    setTimeout(reject, 1000, 1)
  })
}
function p2() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 2)
  })
}
Promise.myAny([p1(), p2()]).then((res) => {
  console.log(res) // 2
})

4、冒泡排序

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

5、选择排序

function selectSort(arr) {
  let len = arr.length
  for (let i = 0; i < len - 1; i  ) {
    // 假设每次循环,最小值就是第一个
    let minIndex = i
    for (let j = i   1; j < len; j  ) {
      // 如果最小值大于其他的值,则修改索引,从而找到真正的最小值
      if (arr[minIndex] > arr[j]) {
        minIndex = j
      }
    }
    // 最小值和第一个交换位置
    [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]
  }
  return arr
}
// test
const arr = [3, 1, 2, 5, 4]
console.log(bubbleSort(arr)) // [1, 2, 3, 4, 5]

6、快速排序

function quickSort(arr) {
  if (arr.length <= 1) return arr
  // 每次取第一个元素作为基准值
  const pivot = arr.shift()
  const left = []
  const right = []
  for (let i = 0; i < arr.length; i  ) {
    if (arr[i] < pivot) {
      // 如果小于基准值,则把它放在左数组
      left.push(arr[i])
    } else {
      // 如果大于等于基准值,则放在右数组
      right.push(arr[i])
    }
  }
  // 递归处理,并把左中右三个数组拼接起来
  return quickSort(left).concat([pivot], quickSort(right))
}
// test
const arr = [3, 1, 2, 5, 4]
console.log(quickSort(arr)) // [1, 2, 3, 4, 5]

7、call

Function.prototype.myCall = function (context = globalThis) {
  // 把方法添加到 context 上,这样使用context[key]调用的时候,内部的 this 就指向了 context
  // 使用 Symbol 防止 context 原有属性被覆盖
  const key = Symbol('key')
  context[key] = this
  const args = [...arguments].slice(1)
  const res = context[key](...args)
  delete context[key]
  return res
}
// test
const myName = { name: 'Jack' }
function say() {
  const [age, height] = arguments
  console.log(`My name is ${this.name}, My age is ${age}, My height is ${height}`)
}
say.myCall(myName, 16, 170) // My name is Jack, My age is 16, My height is 170

8、apply

Function.prototype.myApply = function (context = globalThis) {
  // 把方法添加到 context 上,这样使用context[key]调用的时候,内部的 this 就指向了 context
  // 使用 Symbol 防止 context 原有属性被覆盖
  const key = Symbol('key')
  context[key] = this
  let res
  if (arguments[1]) {
    res = context[key](...arguments[1])
  } else {
    res = context[key]()
  }
  delete context[key]
  return res
}
// test
const myName = { name: 'Jack' }
function say() {
  const [age, height] = arguments
  console.log(`My name is ${this.name}, My age is ${age}, My height is ${height}`)
}
say.myApply(myName, [16, 170]) // My name is Jack, My age is 16, My height is 170

9、bind

Function.prototype.myBind = function (context = globalThis) {
  const fn = this
  const args = [...arguments].slice(1)
  const newFunc = function () {
    const newArgs = args.concat(...arguments)
    if (this instanceof newFunc) {
      // 通过 new 调用,this 为新创建的对象实例,将函数内部的 this 替换为这个新对象
      fn.apply(this, newArgs)
    } else {
      // 普通方式调用,将函数内部的 this 替换为 context
      fn.apply(context, newArgs)
    }
  }
  // 支持 new 调用
  newFunc.prototype = Object.create(fn.prototype)
  return newFunc
}
// test
const myName = { name: 'Jack' }
function say() {
  const [age, height] = arguments
  console.log(`My name is ${this.name}, My age is ${age}, My height is ${height}`)
}
const mySay = say.myBind(myName, 16, 170)
mySay() // My name is Jack, My age is 16, My height is 170

10、instanceof

function myInstanceOf(obj, Fn) {
  // 判断构造函数 Fn 是否出现在 obj 的原型链上
  let proto = Object.getPrototypeOf(obj)
  while (proto) {
    if (proto === Fn.prototype) return true
    proto = Object.getPrototypeOf(proto)
  }
  return false
}

11、new

function myNew(Fn, ...args) {
  const obj = new Object()
  obj.__proto__ = Fn.prototype
  // 将构造函数内部的 this 替换为新对象,并执行构造函数方法
  const res = Fn.apply(obj, args)
  if (typeof res === 'object' && res !== null) {
    // 如果构造函数有返回值,且类型为 object, 则把这个值返回
    return res
  } else {
    return obj
  }
}

12、统计页面中所有标签的种类和个数

function getTagCount() {
  // 获取页面上所有标签元素
  const tags = document.getElementsByTagName('*')
  const tagNames = []
  for (const val of tags) {
    // 把所有标签名转为小写,添加到数组中
    tagNames.push(val.tagName.toLocaleLowerCase())
  }
  const res = {}
  for (const val of tagNames) {
    if (!res[val]) {
      res[val] = 1
    } else {
      res[val]  
    }
  }
  return res
}
// test
console.log(getTagCount()) // { html: 1, head: 1, body: 1, div: 2, script: 1 }

以上就是今天的分享,你是不是全都掌握了呢,欢迎在评论区交流。如果文章对你有所帮助,不要忘了点上宝贵的一赞!

听说点赞的人运气都不差,相信下一个升职加薪的一定是你~😃

相关链接:10个常见的前端手写功能,你全都会吗?

以上就是前端手写功能进阶的详细内容,更多关于前端手写功能的资料请关注Devmax其它相关文章!

常用前端手写功能进阶示例详解的更多相关文章

  1. 前端实现背景虚化但内容清晰且自适应 的实例代码

    这篇文章主要介绍了前端实现背景虚化但内容清晰且自适应 的实例代码,需要的朋友可以参考下

  2. 前端token中4个存储位置的优缺点说明

    这篇文章主要介绍了前端token中4个存储位置的优缺点说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. ajax请求前端跨域问题原因及解决方案

    这篇文章主要为大家介绍了ajax请求前端跨域问题原因及解决方案,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步

  4. 分享10个常见的JavaScript前端手写功能

    这篇文章主要分享10个常见的前端手写功能,防抖、节流、深拷贝、异步控制并发数、继承等功能技巧,具有一定的参考价值,需要的小伙伴可以参考一下

  5. JavaScript架构前端不能没有监控系统原因

    这篇文章主要为大家介绍了为什么前端不能没有监控系统的原因,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  6. 前端必会的轻量打包工具gulp使用详解

    这篇文章主要为大家介绍了前端必会的轻量打包工具gulp使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  7. SpringBoot整合WebSocket实现后端向前端主动推送消息方式

    这篇文章主要介绍了SpringBoot整合WebSocket实现后端向前端主动推送消息方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  8. Springboot实现给前端返回一个tree结构方法

    这篇文章主要介绍了SpringBoot返回给前端一个tree结构的实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  9. React前端开发createElement源码解读

    这篇文章主要为大家介绍了React前端开发createElement源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. vue实现前端展示后端实时日志带颜色示例详解

    这篇文章主要为大家介绍了vue实现前端展示后端实时日志带颜色示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部