JS回调函数练习

最近看了一篇文章为:Mastering Hard Parts of JavaScript
里面主要包含以下部分:

  1. Callbacks & Higher order functions Closure
  2. scope and executioncontext
  3. JavaScript & the event loop
  4. Classes & Prototypes (OOP)

这篇文章列举了很多例子进行练习,有助于我进行学习。

我把这篇文章中我觉得很不错的例子列举出来,然后附上我自己的答案和自己的一些理解。

也欢迎大家一起思考,不要一开始看答案,先尝试自己去写,然后就会发现很多自己觉得很了解的知识点,其实都还有盲区,一点点尝试,一点点成长,每天一个小例子,真的会很开心哦~~。

另外要有其他的答案,欢迎评论区留言,(已完结)

下面开始正篇:

第一部分 Callbacks

Q1

写一个add函数,实现将数组中的值全部加2,其中加2的功能已经提供。
例如:console.log(add([1, 2, 3], addTwo)),输出结果应为[3,4,5]

function addTwo(num) {
   
    return num + 2
}
function add (arr,callback) {
   
  // 要写的代码
}
console.log(add([1, 2, 3], addTwo))

我的答案:

第一种:

function add(arr,callback) {
   
    let newArr = []
    for(let item of arr) {
   
        newArr.push(callback(item))
    }
    return newArr
}

第一种方式使用了for…of…的用法,这里要注意for…of输出的是数组的值,for…in输出的数组的索引,并且输出的索引是字符串哦。

for(let item in arr) {
   
        console.log(typeof item) //string,string,string
        console.log(item) // 0,1,2
    }

第二种:

function add(array, callback) {
   
    const newArr = [];
    array.forEach(item => {
   
      newArr.push(callback(item));
    });
    return newArr;
  }

第三种:

function add (arr,callback) {
   
    let newArray = arr.map(item => callback(item))
    return newArray
}

Q2

模拟累加器的功能,将数组的数值进行加和。注意:不可以直接使用reduce!
例如:数组为[4,1,3],输出的值为8

const nums = [4, 1, 3];
const add = function (a, b) {
   
  return a + b;
}
function reduce() {
   
  // 要写的代码
}
console.log(reduce(nums, add, 0))
console.log(reduce(nums, add))

我的答案:

function reduce(array,callback,initalValue) {
   
    let accum //定义一个累加器
    if(arguments.length > 2) {
    //有初始值
        accum = initalValue
    } else {
    //无初始值
        accum =  array[0]  
        array.shift() //数组第一个值为初始值,需要将第一个值排除
    }    
    array.forEach(item => {
         
        accum = callback(item,accum)
    });
    return accum
}

在这部分中我犯了两个错误:

  1. 我没有考虑到没有初始值的问题:其实else{accum = array[0]}的这部分代码也是看作者的答案才知道的。我们提供给别人一个函数功能时候,其实应该考虑全面,将多种情况都覆盖。另外,这个代码也还有问题,就是我没有加校验和报错,当其他人传一个参数,或者传入的参数不合规时,就会有问题。作为一个例子可以够用,但是作为要提供给其他人用的函数,就还有很多要完善的。
  2. 在我考虑了无初始值之后,添加了条件判断,但是我只考虑了accum = array[0],却忘了将已经作为初始值的数排除,即没有加array.shift()

看着代码没有多少,但是要考虑的问题很多。

Q3

将多个数组中共有的数值提取出来。
例如:[5, 10, 15, 20], [15, 88, 1, 5, 7], [1, 10, 15, 5, 20],[5,12,1,15]); //输出结果为[5,15]

function intersection() {
   
  //代码部分
}
console.log(intersection([5, 10, 15, 20], [15, 88, 1, 5, 7], [1, 10, 15, 5, 20],[5,12,1,15]))

我的答案:

function intersection(...arrays) {
   
  let array =  arrays.reduce((totalArray,currentArray) => {
   
    return currentArray.filter(item => totalArray.includes(item))
  })
  return [...new Set(array)]
}

我的思考:

写这个答案时,我考虑用过map和filter结合的方式,不过后来发现循环好多啊,算了吧… 后来发现reduce和filter结合,真香~~,功能强大代码还少。

  1. 上一题模拟过reduce的简单用法,reduce里面用法有一项就是没有传入初始值时,取传入参数的第一个值。在这题中初始值就是arrays[0]
  2. 在传参数时候,因为不知道参数有多少个,用的扩展运算符(…)
  3. 之前有一个版本的代码,如下:
function intersection(...arrays) {
   
    return arrays.reduce((acc, array) => {
   
        return array.filter((item) => acc.includes(item));
      })
}

这个代码是可以实现题中的答案,但是当我们数组中有重复的数字,如console.log(intersection([5, 5,10, 15, 20], [15, 10, 1, 5, 7], [1, 10, 15, 5, 20],[5,12,1,15])),就会出现问题,因为没有去重。

Q4

返回一个数组,里面包含所有数组的元素,去除重复的元素
例如:[5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5],输出结果为[5, 10, 15, 88, 1, 7, 100]

function union() {
   
// 代码部分
}
console.log(union([5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5])) //[5, 10, 15, 88, 1, 7, 100]

我的答案:
第一种:

function union (...arrays) {
   
  const flatArray = arrays.flat()
  return [...new Set(flatArray)]
}

第二种:

function union(...arrays) {
   
  return arrays.reduce((totalArray,currentArray) => {
   
    let array = currentArray.filter(item => !totalArray.includes(item))
    return totalArray.concat(array)
  })
}

我的思考:
有了上一题的经验,这个功能实现就很容易

Q5

构造一个函数objOfMatches,它接受两个数组和一个回调。objOfMatches将构建一个对象并返回它。为了构建对象,objOfMatches将使用回调测试第一个数组的每个元素,以查看输出是否与第二个数组的相应元素(按索引)匹配。如果存在匹配项,则第一个数组中的元素将成为对象中的键,而第二个数组中的元素将成为对应的值。

例如:

function objOfMatches(array1, array2, callback) {
   
   //代码部分
 }
 
 console.log(
    objOfMatches(
      [&
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值