JavaScript学习笔记(高阶函数一) 2023-03-14 21:26 9阅读 0赞 ### JavaScript学习笔记(高阶函数一) ### * * map/reduce * reduce * filter * 回调函数 * sort * Array * * every * find * findIndex * forEach * 闭包 * * 函数作为返回值 * 闭包 function add(x,y,f){ return f(x) + f(y); } //将Math.abs作为f传入add函数 var x = add(-5,6,Math.abs); console.log('add:'+x); ![20200518102306686.png][] ## map/reduce ## 如果我们想把一个函数f(x)=X2作用在一个数组\[1,2,3,4,5,6\]中,那么要怎么实现呢? 首先先用传统的方法来实现 //定义一个函数 var f = function(x){ return x * x; } var arr = [1,2,3,4,5,6]; var result = []; for (var i = 0; i < arr.length; i++) { //将调用函数的结果push到新的数组中 result.push(f(i)); } //遍历结果数组 console.log('传统方式:'+result); ![在这里插入图片描述][20200518104733677.png] 由于map()方法定义在JavaScript的Array中,我们调用Array的map()方法,传入到我们自己的数组中, //定义一个函数 function pow(x){ return x * x; } var arr = [1,2,3,4,5,6]; var result = arr.map(pow); console.log('map方式:'+result); ![20200518104622945.png][] 我们这样做一行就搞定了,是不是特别的方便!当然我们也可以有其他的功能,比如: 将Array中的所有数字转为字符串: var arr = [1,2,3,4,5,6]; console.log(arr.map(String)); ![20200518105211823.png][] 使用map将字符串变成整数 var arr=['1','2','3']; var r; r = arr.map(Number); ![20200518145014314.png][] ## reduce ## 再看reduce的用法,Array的reduce()把一个函数作用在这个Array的【x1,x2,x3…】上,这个函数必须接收两个参数. 比如对一个Array求和,就可以用reduce实现: var arr = [1,2,3,4,5,6]; console.log(arr.reduce(function(x,y){ return x + y; })); ![20200518110729835.png][] 要把\[1,2,3,4,5\]变换成整数12345,reduce()也能派上用场: ## filter ## filter是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素 和map()类似,Array的filter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。 例如:在一个Array中,删掉偶数,只保留奇数,可以写: var arr = [1, 2, 4, 5, 6, 9, 10, 15]; var r = arr.filter(function(x){ return x % 2 !== 0; }); console.log(r); ![20200518153023521.png][] 那么把一个Array中的空字符串删除,可以写成: var arr = ['A', '', 'B', null, undefined, 'C', ' ']; var r = arr.filter(function(s){ return s && s.trim(); }); console.log(r); ![20200518153322184.png][] 由此可以看出filter()这个高阶函数,关键在于正确实现一个“筛选”函数 ## 回调函数 ## filter()接收的回调函数,其实可以有多个参数 ,通常我们仅使用 第一个参数 表示元素的位置和数组本身: var arr =['a','b','c']; /** * element 数组中的目标元素 * index 数组中的元素的索引 * index 整个数组 */ var r = arr.filter(function(element,index,self){ console.log(element); console.log(index); console.log(self); return true; }); ![20200518154543564.png][] 利用filter,可以巧妙的 去除Array的重复元素: var r,arr = ['apply','strawberry','banana','pear','apply','orange','orange','strawberry']; r = arr.filter(function(element,index,self){ //数组元素对应的目标元素和数组中索引相同时就返回,这样就达到了去掉重复项 return self.indexOf(element) == index; }); console.log(r.toString()); ![20200518155019327.png][] ## sort ## 排序算法 排序也是程序中经常用到的算法,无论使用冒泡排序还是快速,排序的核心是比较两个元素的大小。如果是数字,我们可以直接比较,但如果字符串或者两个对象呢?直接 比较数学上的大小是没有意义的,因此,比较的过程必须通过函数抽象出来。通常规定,对于两个元素x和y,如果认为x<y,则返回-1,如果认为x == y,则返回0,如果认为x>y,则返回1,这样,排序算法就不用关心具体的比较过程,而是根据比较结果的直接排序。 JavaScript的Array的sort()方法就是使用排序的,但是排序结果可能让你大吃一惊: var arr = [1,34,6,0]; console.log(arr.sort()); ![20200518165016292.png][] 我们可以这样写排序 var arr = [1,34,6,0]; // console.log(arr.sort()); arr.sort(function(x,y){ if(x < y){ return -1; } if(x > y){ return 1; } return 0; }); console.log(arr); ![20200518165227556.png][] 倒序也是一样的原理: var arr = [1,34,6,0]; // console.log(arr.sort()); arr.sort(function(x,y){ if(x > y){ return -1; } if(x < y){ return 1; } return 0; }); console.log(arr); ![202005181653197.png][] 默认情况下,对字符串排序,是按照ASCII的大小比较的,现在,我们提出排序应该忽略大小写,按照字母排序,要实现这个算法,不必对现在代码在加改动,只要我们能定义出忽略大小写的比较算法就可以实现排序了: var arr = ['Google', 'apple', 'Microsoft']; arr.sort(function(s1,s2){ //将字母转换为大写 x1 = s1.toUpperCase(); x2 = s2.toUpperCase(); if(x1 < x2){ return -1; } if(x1 > x2){ return 1; } return 0; }); console.log(arr); ![在这里插入图片描述][20200518170041433.png] 这样就排序成功了! ## Array ## 对于数组,除了map()、reduce、filter()、sort()这些方法可以传入一个函数外,Array对象还提供了很多非常实用的高阶函数。 ### every ### every()方法可以判断数组的所有元素是否满足测试条件 例如: 判断当前数组中的元素长度是否大于0 var arr = ['Apple','pear','orange']; console.log(arr.every(function (s){ return s.length > 0; }));//true,每个元素都满足s.length>0 console.log(arr.every(function (s){ return s.toLowerCase() === s; }));//false,因为不是每个元素都全部是小写 ![20200518170844872.png][] ### find ### find()方法用于查找符合条件的第一个元素,如果找到 了,返回这个元素,否则,返回undefined; var arr = ['Apple','pear','orange','HKK']; console.log(arr.find(function (s){ return s.toLowerCase() === s; }));//'pear',因为pear全部是小写 console.log(arr.find(function (s){ return s.toUpperCase() === s; }));//'HKK',因为HKK全部是大写的 ![20200518171443617.png][] ### findIndex ### var arr = ['Apple','pear','orange','HKK']; console.log(arr.findIndex(function (s){ return s.toLowerCase() === s; }));//1.因为'pear'的索引是1 console.log(arr.findIndex(function (s) { return s.toUpperCase() === s; }));//3,因为'HKK'的索引是3 ![20200518172102930.png][] ### forEach ### forEach()和map()类似,它也把每个元素依次作用于传入的函数,但不会返回新的数组。forEach()常用于遍历数组,因此,传入的函数不需要返回值: var arr = ['Apple','pear','orange','HKK']; arr.forEach(console.log);//依次打印 每个元素 ![20200518172406116.png][] ## 闭包 ## ### 函数作为返回值 ### //我们不是立刻得到进行求和,而是在后面的代码中使用,就先保存求和的函数! function lazy_sum(arr) { //定义一个函数用于求和 var sum = function(){ return arr.reduce(function (x,y) { return x + y; }); } return sum; } //调用lazy_sum时其实是[Function: sum]函数 var f = lazy_sum([1,2,3,4,5,6,7,8,9,10]); //这里才是真正的调用 console.log(f()); ![20200518175350470.png][] 总结:在上面这个例子中,我们在函数 lazy\_sum中又定义了一个函数sum,内部函数sum可以引用外部函数lazy\_sum的参数和局部变量,当lazy\_sum返回函数sum时 ,相关参数和变量都保存在返回的函数 中,这种称为"闭包(Closure)"的程序结构拥有极大的威力。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mjg5MzA4NQ_size_16_color_FFFFFF_t_70][] 这两次的调用每次都会返回一个新的函数,虽然传入的是相同 的参数 ,但是调用的结果不互相影响! ### 闭包 ### 注意到返回的函数在其定义内部引用了局部变量arr,所以,当现代战争函数 返回一个函数后,其内部的局部变量还被新函数引用,所以,闭包用起来简单,实现起来可没有那么容易。 另一个需要注意的问题是,返回的函数 并没有立即执行,而是直到调用了f()才执行,我们来看一个例子: function count() { var arr = []; for(var i = 1;i<= 3;i++){ arr.push(function () { return i * i; }); } return arr; } var results = count(); var f1 = results[0]; var f2 = results[1]; var f3 = results[2]; console.log(f1()); console.log(f2()); console.log(f3()); 你可能认为调用的结果为1,4,9,只是实际的结果是: ![20200521133516832.png][] 原因在于,返回的函数引用了变量i,但它并非立刻执行。而是3个函数 都返回时,它们所引用的变量i已经变成 了4,所以最终的 结果为16. 返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。 如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变: function count() { var arr = []; for(var i = 1;i<= 3;i++){ arr.push((function (n) { return function () { return n * n; } })(i)); } return arr; } var results = count(); var f1 = results[0]; var f2 = results[1]; var f3 = results[2]; console.log(f1()); console.log(f2()); console.log(f3()); ![在这里插入图片描述][20200521154318555.png] 这里“创建一个匿名函数并立刻执行”的语法 : (function (x) { return x * x; })(3); 闭包可以返回一个函数 延迟执行,但是他还有更强大 的功能: 在面向对象的程序设计语言里,比如Java和C++,要在对象内部封装一个私有变量,可以用private 修饰一个成员变量。 在没有class机制,只有函数 的语言里,借助闭包,同样可以封装一个私有变量。我们用js创建一个计数器: function create_counter(initial) { var x = initial || 0; return{ inc:function () { x += 1; return x; } } } var c1 = create_counter(); console.log(c1.inc()); console.log(c1.inc()); console.log(c1.inc()); ![20200521155402338.png][] 在返回的对象中,实现了一个闭包,该闭包携带了局部变量x,并且,从外部代码根本无法访问到变量x。换句话说,闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来。 例如,要计算xy可以用Math.pow(x, y)函数,不过考虑到经常计算x2或x3,我们可以利用闭包创建新的函数pow2和pow3: //定义一个函数,内部含有一个函数 function make_pow(n){ return function (x) { return Math.pow(x,n); } } var pow2 = make_pow(2); var pow3 = make_pow(3); console.log(pow2(5)); console.log(pow3(7)); ![20200521155825716.png][] [20200518102306686.png]: /images/20230312/31dc86337bee4555905d681316c4c329.png [20200518104733677.png]: /images/20230312/d9a8f53203814e1bb33e581cd23f0d0b.png [20200518104622945.png]: /images/20230312/4940bc4ba263440db7ba39c5dc50770c.png [20200518105211823.png]: /images/20230312/c961a68281d74124a3d60612b12934f4.png [20200518145014314.png]: /images/20230312/141db49b5a5e4e6497822bac00d346d7.png [20200518110729835.png]: /images/20230312/7baddb5986914b098186f46f3c08d00f.png [20200518153023521.png]: /images/20230312/42afa7603fc04cc6823f478175ac8daa.png [20200518153322184.png]: /images/20230312/b85867d10d434cdba3aa2f2a8ebf4372.png [20200518154543564.png]: /images/20230312/b2f3f652f65d41aa8a1856024d56307e.png [20200518155019327.png]: /images/20230312/d0517f37a86e49f19ebe5619cf74a96e.png [20200518165016292.png]: /images/20230312/c165ac349d474ee387aabeffc1f44e2c.png [20200518165227556.png]: /images/20230312/34d4014df08c4fb89f16306232048008.png [202005181653197.png]: /images/20230312/34a855afd0f140a1bdd00ed0189945a5.png [20200518170041433.png]: /images/20230312/2225abeda96f4d47bfe3b8f48b9401b2.png [20200518170844872.png]: /images/20230312/0b5f8134d95240a3a0095cb256aad047.png [20200518171443617.png]: /images/20230312/cc26aaec4b864851a9a3454bfa29e95a.png [20200518172102930.png]: /images/20230312/d9d2825cc85e482f8d96bfcef56bbec1.png [20200518172406116.png]: /images/20230312/b7f0b4d67c02496c82c6d5fc2d2c9fd3.png [20200518175350470.png]: /images/20230312/ce1152eef28d48b183bf18e1f3f63382.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mjg5MzA4NQ_size_16_color_FFFFFF_t_70]: /images/20230312/779b5d4fb75c433286da05a2a964c2e6.png [20200521133516832.png]: /images/20230312/5f75879520324bfaae7385d48742d5a4.png [20200521154318555.png]: /images/20230312/3ec19fced5ac4389b66a4822ff65967c.png [20200521155402338.png]: /images/20230312/187cae4501b14b7fa0d789ba4d07f335.png [20200521155825716.png]: /images/20230312/bb5605fb700f4601a844a1aa15fbea94.png 文章版权声明:注明蒲公英云原创文章,转载或复制请以超链接形式并注明出处。
相关 高阶函数 百度百科的解释: 在数学和计算机科学中,高阶函数是至少满足下列一个条件的函数: ①接受一个或多个函数作为输入; ②输出一个函数 第一个条件就是:函数作为参数传入 灰太狼/ 2021年08月19日 23:42/ 0 赞/ 251 阅读
相关 JavaScript高阶函数应用 <template> <div class=""> </div> </template> <script> export default 我会带着你远行/ 2021年09月08日 23:36/ 0 赞/ 151 阅读
相关 高阶函数(一) 1 什么是高阶函数 1.1 高阶函数的基本概念 高阶函数其实看着挺吓人,不过就是把函数作为参数或者返回值的一类函数而已。其实这样的函数我们都见过很多了,来看个例子: 刺骨的言语ヽ痛彻心扉/ 2022年04月25日 15:24/ 0 赞/ 87 阅读
相关 [Scala] Scala 学习笔记 (4) - 高阶函数 (待补充) 高阶函数 高阶函数 map:对集合中的每一个元素都做一个操作 foreach:循环遍历集合 filter:过滤结 青旅半醒/ 2022年05月19日 19:38/ 0 赞/ 62 阅读
相关 Python之高阶函数(一) 高阶函数引入 高阶函数英文叫Higher-order function。什么是高阶函数?我们以实际代码为例子,一步一步深入概念。 大家都很熟悉abs()函数吧,这个函 川长思鸟来/ 2022年05月20日 18:11/ 0 赞/ 74 阅读
相关 JavaScript学习记录day7-高阶函数 JavaScript学习记录day7-高阶函数 @(学习)\[javascript\] JavaScript学习记录day7-高阶函数 什 比眉伴天荒/ 2022年05月31日 16:23/ 0 赞/ 49 阅读
相关 高阶函数(一) > 原文链接:[https://github.com/enbandari/Kotlin-Tutorials][https_github.com_enbandari_Kotlin 电玩女神/ 2022年06月08日 18:56/ 0 赞/ 64 阅读
相关 JavaScript的高阶函数笔记 今天和一位老师学习了高阶函数,感觉非常有用,做个笔记。 我学习的JavaScript三个高阶函数是filter/map/reduce,高阶函数真的很不错,我打个比方吧,如果说 短命女/ 2022年11月15日 19:49/ 0 赞/ 25 阅读
相关 【kotlin】Kotlin笔记16-高阶函数(函数类型) Kotlin笔记16-高阶函数 10.1 高阶函数 定义高阶函数 <table> <thead> <tr> <th>序号</th> た 入场券/ 2022年11月17日 19:27/ 0 赞/ 26 阅读
相关 JavaScript学习笔记(高阶函数一) JavaScript学习笔记(高阶函数一) map/reduce reduce filter 回调函数 朱雀/ 2023年03月14日 21:26/ 0 赞/ 10 阅读
还没有评论,来说两句吧...