• 手撕js中常见方法


    array.fill

    1. Array.prototype.fill2 = function (value, start, end) {
    2. const length = this.length; // 获取数组的长度
    3. start = start >> 0; // 将start转换为整数
    4. // 如果end参数未填写,则默认为数组的长度,否则将end转换为整数
    5. end = typeof end === 'undefined' ? length : end >> 0;
    6. // 将start限制在合法范围内,最小值为0,最大值为数组的长度
    7. start = start >= 0 ? Math.min(start, length) : Math.max(start + length, 0);
    8. // 将end限制在合法范围内,最小值为0,最大值为数组的长度
    9. end = end >= 0 ? Math.min(end, length) : Math.max(end + length, 0);
    10. // 使用指定的value填充从start到end范围内的数组索引
    11. while (start < end) {
    12. this[start] = value;
    13. start++;
    14. }
    15. // 返回被修改后的数组
    16. return this;
    17. }

    这段代码实现了一个自定义的fill2方法,用于在数组中指定的范围内填充指定的值。它接受三个参数:value表示要填充的值,start表示填充的起始索引,end表示填充的结束索引(不包含在内)。

    在代码中,首先获取了数组的长度。然后对start和end参数进行处理,将它们转换为整数,并进行范围限制,确保它们在合法的范围内。接下来,使用一个循环从start索引开始,逐个将数组的元素设置为指定的value值,直到达到end索引为止。最后,返回被修改后的数组。

    通过使用这个自定义的fill2方法,我们可以在数组中指定的范围内快速填充指定的值。 

    array.map

    1. Array.prototype.myMap = function (callbackFn, thisArg) {
    2. if (this == "undefined" || this == "null") {
    3. throw new TypeError("can not read property 'map' of undefined or null");
    4. }
    5. if (typeof callbackFn !== "function") {
    6. throw `${callbackFn} is not a function`;
    7. }
    8. let O = Object(this); // 将当前数组对象转换为对象类型
    9. let T = thisArg; // 设置回调函数的this值
    10. let len = O.length >>> 0; // 获取数组的长度
    11. let A = new Array(len); // 创建一个新的数组,用于存储映射后的值
    12. for (let k = 0; k < len; k++) {
    13. for (k in O) {
    14. let KValue = O[k]; // 获取当前索引的值
    15. let mapValue = callbackFn.call(T, KValue, k, O); // 调用回调函数进行映射操作
    16. A[k] = mapValue; // 将映射后的值存储到新数组中
    17. }
    18. }
    19. return A; // 返回映射后的新数组
    20. }
    21. let arr = [1, 2, 3, 4];
    22. let arr2 = arr.myMap(function (currentValue, index, Array) {
    23. console.log(currentValue, index, Array);
    24. return currentValue + 1;
    25. });
    26. console.log(arr2);
    1. Array.prototype.myMap = function (callbackFn, thisArg) {
    2. if (this == "undefined" || this == "null") {
    3. throw new TypeError("can not read property 'map' of undefined or null")
    4. }
    5. if (typeof callbackFn !== "function") {
    6. throw `${callbackFn} is not a function`
    7. }
    8. let length = Object(this).length >>> 0
    9. let newArrray = []
    10. let i = 0
    11. while (i < length) {
    12. if (i in this) {
    13. //2. call修改了函数callbackFn的this指向,指向thisArg,后面的this还是指向的 arr,作为参数传给函数
    14. newArrray.push(callbackFn.call(thisArg, this[i],i,this))
    15. }
    16. i++
    17. }
    18. return newArrray
    19. }
    20. let arr = [1,2,3,4]
    21. // 1.绑定实例:用类实例对象去调用成员方法,此时this的指向为调用的实例对象 arr
    22. let arr2 = arr.myMap(function(currentValue,index,Array){
    23. // 3.此时的参数 currentValue,index,Array 对应2.传入的参数:this[i],i,this
    24. // 此时this为callbackFn的指向 this.Args 也就是 {message:"🐟"}
    25. console.log(currentValue,index,Array,this);
    26. return ++currentValue
    27. },{message:"🐟"})
    28. console.log(arr2);

    节流函数

    1. function myThrottle(myFn,myDelay){
    2. let initState = true
    3. return function(...args){
    4. if(!initState) return
    5. initState = false
    6. setTimeout(() => {
    7. myFn.apply(this,args)
    8. initState = true
    9. }, myDelay);
    10. }
    11. }
    12. function mytest(arguments){
    13. console.log('test'+ arguments); //testppp
    14. }
    15. const oneTest = myThrottle(mytest,500)
    16. oneTest('ppp')

    防抖函数

    1. function debounce(fn,delay){
    2. var initWaitTime = null
    3. return function(...args){
    4. clearTimeout(initWaitTime)
    5. initWaitTime = setTimeout(() => {
    6. fn.apply(this,args)
    7. },delay)
    8. }
    9. }
    10. function testDebounce(){
    11. console.log('防抖');
    12. }
    13. const test4 = debounce(testDebounce,1000)
    14. console.log(test4);
    15. test4()
    16. test4()
    17. test4()

    异步并发调度器Scheduler

    1. class Scheduler {
    2. constructor(max) {
    3. this.max = max
    4. this.count = 0
    5. this.queue = []
    6. }
    7. add(p) {
    8. this.queue.push(p)
    9. this.start()
    10. }
    11. start() {
    12. if (this.count >= this.max || !this.queue.length) return
    13. this.count++
    14. this.queue.shift()().finally(() => {
    15. this.count--
    16. this.start()
    17. })
    18. }
    19. }
    20. // 延迟函数
    21. const sleep = time => new Promise(resolve => setTimeout(resolve, time));
    22. // 同时进行的任务最多2个
    23. const scheduler = new Scheduler(2);
    24. // 添加异步任务
    25. // time: 任务执行的时间
    26. // val: 参数
    27. const addTask = (time, val) => {
    28. scheduler.add(() => {
    29. return sleep(time).then(() => console.log(val));
    30. });
    31. };
    32. addTask(1000, '1');
    33. addTask(500, '2');
    34. addTask(300, '3');
    35. addTask(400, '4');
    36. // 2
    37. // 3
    38. // 1
    39. // 4
    1. class Scheduler {
    2. constructor(maxNum) {
    3. this.maxNum = maxNum; // 最大同时执行任务的数量
    4. this.count = 0; // 当前正在执行的任务数量
    5. this.taskList = []; // 任务列表,用于存储待执行的任务
    6. }
    7. addTask(time, val) {
    8. this.taskList.push([time, val]); // 将任务添加到任务列表中
    9. }
    10. start() {
    11. if (!this.taskList.length) return; // 如果任务列表为空,则直接返回
    12. if (this.count < this.maxNum) { // 如果当前正在执行的任务数量小于最大值
    13. const [time, val] = this.taskList.shift(); // 从任务列表中取出一个任务
    14. this.count++; // 增加正在执行的任务数量
    15. setTimeout(() => { // 使用setTimeout延迟执行任务
    16. console.log(val); // 打印任务的值
    17. this.count--; // 减少正在执行的任务数量
    18. this.start(); // 继续执行下一个任务
    19. }, time * 1000); // 将时间转换为毫秒,并设置延迟执行的时间
    20. this.start(); // 继续执行下一个任务
    21. }
    22. }
    23. }

    深拷贝函数:

    1. function deepClone(target, hashMap = new WeakMap()) {
    2. // 基本数据类型,直接返回
    3. if (typeof target !== "object" || target == null) {
    4. /*
    5. 函数,则调用函数并返回结果(虽然这里是同一个存储空间
    6. 但是如果修改函数时,相当于重写函数,会自动分配堆内存存放新函数,也就是不会改变原函数)
    7. */
    8. if (target instanceof Function) return target.call(this, ...arguments);
    9. return target;
    10. }
    11. // 日期对象,则创建一个新的日期对象并返回
    12. if (target instanceof Date) return new Date(target);
    13. // 正则表达式对象,则创建一个新的正则表达式对象并返回
    14. if (target instanceof RegExp) return new RegExp(target);
    15. // 创建一个与目标对象构造函数相同的新对象
    16. let res = new target.constructor();
    17. // 如果哈希表中已经存在目标对象,则直接返回对应的新对象
    18. if (hashMap.get(target)) return hashMap.get(target);
    19. // 将新对象和目标对象存入哈希表中
    20. hashMap.set(res, target);
    21. // 遍历目标对象的属性
    22. for (let key in target) {
    23. // 递归调用深拷贝函数,复制目标对象的属性值,并赋值给新对象的对应属性
    24. res[key] = deepClone(deepClone(target[key], hashMap));
    25. }
    26. // 返回新对象
    27. return res;
    28. }

  • 相关阅读:
    经典文献阅读之--BoW3D
    拓世AI文生图、AI直播一体机,直播间搭建从未如此简单
    微信小程序- css相比,wxss区别?小程序关联微信公众号如何确定用户的唯一性?微信小程序中的用户ID(openid和unionid)
    【工作笔记】数据库死锁的排查和数据库锁知识记录
    数据库原理及应用实验报告-实验10-触发器
    springboot+vue+elementUI 公司财务固定资产管理系统#毕业设计
    JSP课设:学生选课系统(附源码+调试)
    Android在app中实现蓝牙服务Service的案例
    Chrome安装zotero connector 插件
    【JVM】类的生命周期
  • 原文地址:https://blog.csdn.net/aybaiwan/article/details/132774909