我们向您介绍
Sukhjinder Arora发表在《
零碎 》上的文章的
译文 。 深入了解JavaScript中的高阶函数以及该语言内置的其他一些函数。
图片来自NESA,来自Makers,来自Unsplash学习JavaScript编程,您可能会遇到
高阶函数的概念。 尽管这个概念似乎令人生畏,但实际上并没有那么复杂。
由于具有处理高阶函数的能力,JavaScript适用于函数式编程。
高阶函数在JavaScript中很常见。 如果您与他一起工作了一段时间,很可能您甚至没有意识到就使用了这些功能。
要全面了解高阶函数,您首先需要了解什么是
函数编程和一等函数 。
提示 :重用JavaScript函数通常会导致重复。 为了避免这种情况,请使用
Bit(GitHub) 。 您可以轻松地找到新功能,共享它们并以最小的管理更改将它们重新应用。 试试吧,不要害羞。
什么是函数式编程
在不赘述的情况下,函数式编程是这样一种编程,其中某些函数作为参数传递给其他函数,然后将第三个函数作为值返回。 在函数式编程中,我们考虑并使用函数进行操作。
函数式编程是用JavaScript,Haskell,Clojure,Scala和Erlang等语言完成的。
什么是一流的功能
在学习使用JavaScript时,您最有可能听说过,函数是一等公民。 事实是,在JavaScript中,就像任何其他函数式编程语言一样,函数是对象。
专门针对JavaScript的函数是一种特殊的对象(
Function
对象或函子)。 例如:
function greeting() { console.log('Hello World'); }
为了说明JavaScript中的函数是对象,我们可以执行以下操作:
注意:尽管以上在JavaScript中都可以正常使用,但您不应滥用它。 您不能将随机属性分配给函子-最好使用常规对象。
在JavaScript中,您可以使用其他实体执行的所有操作(例如对象,字符串或数字)都适用于函数。 可以将它们作为参数传递给其他函数(然后称为回调函数或回调函数),将它们分配给变量,依此类推。 这就是为什么JavaScript函数被称为一流函数的原因。
将函数分配给变量
JavaScript允许您将函数分配给变量。 例如:
const square = function(x) { return x * x; }
它们也可以被传输。 例如:
const foo = square;
将函数作为参数传递
我们可以将函数作为参数传递给其他函数。 例如:
function formalGreeting() { console.log("How are you?"); } function casualGreeting() { console.log("What's up?"); } function greet(type, greetFormal, greetCasual) { if(type === 'formal') { greetFormal(); } else if(type === 'casual') { greetCasual(); } }
因此,既然我们知道什么是一流的函数,那么让我们来看一下JavaScript中的高阶函数。
高阶函数
高阶函数是与其他函数一起使用的函数,以一个函数作为参数,或者返回一个函数作为结果。
该语言已内置的高阶函数的示例是
Array.prototype.map
,
Array.prototype.filter
和
Array.prototype.reduce
。
高阶函数的作用
让我们看一些高阶内置函数的示例,并将它们与不使用高阶函数的解决方案进行比较。
Array.prototype.mapmap()
方法创建一个新数组,并为初始数组的每个元素调用传递的函数。
map()
方法获取回调函数的每个值,并使用这些值创建一个新数组。
传递给
map()
方法的回调函数采用三个参数:
element
,
index
和
array
。
考虑一些例子。
示例1假设我们有一个数字数组,然后我们要从中创建一个新数组,其中初始数组中的每个数字都会加倍。 有无高阶函数如何解决这个问题?
没有高阶函数: const arr1 = [1, 2, 3]; const arr2 = []; for(let i = 0; i < arr1.length; i++) { arr2.push(arr1[i] * 2); }
使用高阶
map
功能:
const arr1 = [1, 2, 3]; const arr2 = arr1.map(function(item) { return item * 2; }); console.log(arr2);
使用箭头功能可以使代码更短。
const arr1 = [1, 2, 3]; const arr2 = arr1.map(item => item * 2); console.log(arr2);
示例2假设我们有一个包含几个人的出生年数的数组,然后我们要从中创建一个新数组,以说明他们的年龄。
没有高阶函数: const birthYear = [1975, 1997, 2002, 1995, 1985]; const ages = []; for(let i = 0; i < birthYear.length; i++) { let age = 2018 - birthYear[i]; ages.push(age); }
使用高阶
map
功能:
const birthYear = [1975, 1997, 2002, 1995, 1985]; const ages = birthYear.map(year => 2018 - year);
Array.prototype.filterfilter()
方法创建一个新数组,其中所有元素都通过了传递函数中指定的测试。 传递给
filter()
的回调函数采用三个参数:
element
,
index
和
array
。
考虑一些例子。
示例1想象一下,我们有一个包含对象的数组,这些对象的属性为“名称”和“年龄”。 从中我们想创建一个新的数组,其中仅指示成年人(18岁及以上)。
没有高阶函数: const persons = [ { name: 'Peter', age: 16 }, { name: 'Mark', age: 18 }, { name: 'John', age: 27 }, { name: 'Jane', age: 14 }, { name: 'Tony', age: 24}, ]; const fullAge = []; for(let i = 0; i < persons.length; i++) { if(persons[i].age >= 18) { fullAge.push(persons[i]); } } console.log(fullAge);
使用高阶
filter
功能:
const persons = [ { name: 'Peter', age: 16 }, { name: 'Mark', age: 18 }, { name: 'John', age: 27 }, { name: 'Jane', age: 14 }, { name: 'Tony', age: 24}, ]; const fullAge = persons.filter(person => person.age >= 18); console.log(fullAge);
Array.prototype.reducereduce
方法将一个函数应用于数组的每个值,将其简化为单个值。 reduce方法有两个参数:
- 要处理的回调函数;
- 可选的
initialValue
参数(第一个函数调用的第一个参数)。
回调函数采用四个参数:
accumulator
,
currentValue
,
currentIndex
,
sourceArray
。
如果传递了
initialValue
参数,则
accumulator
参数将等于
initialValue
参数,而
currentValue
参数
currentValue
成为数组的第一个元素。
如果未传递
initialValue
参数,则
accumulator
参数将等于数组的第一个元素,而数组的第二个元素将被当作
currentValue
参数。
示例1假设我们需要找到一个数组中数字的总和。
使用高阶函数
reduce
:
const arr = [5, 7, 1, 8, 4]; const sum = arr.reduce(function(accumulator, currentValue) { return accumulator + currentValue; });
每次将回调函数应用于数组中的每个值时,
accumulator
参数都会保存该函数返回的上一个操作的结果,而
currentValue
将使用数组的下一个值。 完成后,结果存储在变量
sum
。
另外,我们可以向该函数传递初始值:
const arr = [5, 7, 1, 8, 4]; const sum = arr.reduce(function(accumulator, currentValue) { return accumulator + currentValue; }, 10);
没有高阶函数:
const arr = [5, 7, 1, 8, 4]; let sum = 0; for(let i = 0; i < arr.length; i++) { sum = sum + arr[i]; }
如您所见,借助高阶函数,可以使代码更整洁,更短且功能更丰富。
创建自己的高阶函数
到目前为止,我们已经考虑了该语言内置的各种高阶函数。 是时候创建自己的高阶函数了。
想象一下,JavaScript将没有自己的
map
方法。 我们可以自己构建它,从而创建我们自己的高阶函数。
假设我们有一个字符串数组,然后我们要从中创建一个整数数组,其中每个元素都将代表初始数组中字符串的长度。
const strArray = ['JavaScript', 'Python', 'PHP', 'Java', 'C']; function mapForEach(arr, fn) { const newArray = []; for(let i = 0; i < arr.length; i++) { newArray.push( fn(arr[i]) ); } return newArray; } const lenArray = mapForEach(strArray, function(item) { return item.length; });
在上面的示例中,我们创建了一个高阶函数
mapForEach
,它使用一个数组和一个回调函数
fn
作为参数。 此函数循环应用于数组的每个元素,并在每次迭代中将
fn
回调函数作为
newArray.push
函数
newArray.push
一部分进行
newArray.push
。
fn
回调函数采用初始数组的当前元素,并返回此元素的长度值,该值存储在新的
newArray
内部。 迭代完成后,将
newArray
数组作为结果返回并分配给
lenArray
数组。
结论
我们了解了什么是高阶函数,并研究了该语言内置的一些函数。 我们还学习了如何创建自己的高阶函数。
简而言之,高阶函数的工作方式与常规函数类似,但是具有将其他函数作为参数接收并作为结果返回的附加功能。
实际上,仅此而已。 如果您发现这篇文章对您有所帮助,也可以在
Medium和
Twitter上关注我。 如有任何疑问,请随时发表评论! 我很乐意提供帮助。 :)