JS 5高阶函数分享

目录
  • 1、前言
  • 2、递归
  • 3、回调函数
    • 3.1匿名回调函数
    • 3.2带参数的回调函数
    • 3.3回调函数的优缺点
  • 4、自调函数
  • 5、为值的函数
  • 6、闭包

1、前言

在JavaScript中,函数实际上也是一个数据,也就是说函数也可以赋值给一个变量。本篇文章就来介绍一些JavaScript中的高阶函数的用法。

2、递归

所谓的递归,就是指函数自己调用自己;用一个故事来说呢就是:从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?“从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?‘从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?……'” 。

从某种意义上说,递归近似于循环。两者都重复执行相同的代码,并且两者都需要一个终止条件,以避免无限循环或者无限递归。

递归所需要的必要条件如下:

  • 子问题跟原始问题一样,且更为简单
  • 必须有个出口

在JavaScript中想要递归调用存在两种方式

  • 通过使用函数名实现
  • 通过使用arguments.callee属性实现。

如下代码展示了简单的递归:

var v = 1 // 出口条件
function fun() {
  console.log('第' + v + '次调用函数')
  v++
  if (v <= 3) {
    fun()
  }
}
fun()

执行结果如下

第1次调用函数
第2次调用函数
第3次调用函数

3、回调函数

然函数与任何可以被赋值给变量的数据是相同的,那么它当然可以像其他数据那样被定义、删除、拷贝,以及当成参数传递给其他函数。

当一个函数作为参数传递给另一个函数时,作为参数的函数被称之为回调函数。作为使用回调函数的函数称为目标函数(外层函数)

示例代码如下所示:

// 定义一个函数,这个函数有两个函数类型的参数,然后分别执行那两个函数,并返回它们的和。
function sum(a, b) {
  // 目标函数
  return a() + b()
}

function one() {
  // 回调函数
  return 1
}

function two() {
  // 回调函数
  return 2
}

console.log(sum(one, two)) // 3

代码执行流程如下:

当执行sum函数时,传入两个实参,在sum函数中,会将两个实参作为函数执行,并将返回值计算并返回。

3.1匿名回调函数

所谓匿名回调函数,就是目标函数中的参数是没有名称的函数,将上一段代码修改为使用匿名回调函数

// 定义一个函数,这个函数有两个函数类型的参数,然后分别执行那两个函数,并返回它们的和。
function sum(a, b) {
  // 目标函数
  return a() + b()
}

console.log(
  sum(
    function () {
      // 匿名回调函数
      return 1
    },
    function () {
      //  匿名回调函数
      return 2
    },
  ),
) // 3

3.2带参数的回调函数

回调函数是可以增加参数的,示例代码如下:

function multiplyByTwo(list, callback) {
  list.forEach(function (v, i) {
    callback(v * 2, i)
  })
}
var list = [1, 2, 3]
multiplyByTwo(list, function (v, i) {
  list[i] = v
})
console.log(list) // [ 2, 4, 6 ]

3.3回调函数的优缺点

  • 匿名回调函数节省了全局命名空间
  • 将私有的数据内容开放给指定位置使用
  • 保证封装性——虽然可以使用私有数据,但是并不知道来源
  • 有助于提升性能

但是回调函数也是有缺点的,当目标函数的参数是一个回调函数时,回调函数的参数又是另一个回调函数,另一个回调函数的参数还是一个回调函数…也就是套娃,也就形成了回调陷阱,严重一点可以说回调地狱。

4、自调函数

所谓的自调函数,就是定义后立即调用的函数,示例代码如下所示:

;(function () {
  console.log('自调函数')
})()

这种语法看上去有点唬人,其实没有什么,我们只需将匿名函数的定义放进一对括号中,然后外面再紧跟一对括号即可。

语法结构如下图所示:

自调函数除了以上两种方式外,还有以下几种不常用的方式,示例代码如下:

;+(function (v) {
  // 形参
  var w = 100 // 局部变量
  console.log('自调函数' + v)
})(1) // 实参

!(function (v) {
  var w = 100 // 局部变量
  console.log('自调函数' + v)
})(2)

~(function (v) {
  var w = 100 // 局部变量
  console.log('自调函数' + v)
})(3)

使用自调匿名函数的好处是不会产生任何全局变量。

缺点在于这样的函数是无法重复执行的(除非将它放在某个循环或其他函数中)。这也使得即时函数非常适合于执行一些一次性的或初始化的任务。

5、为值的函数

将一个函数作为另一个函数的结果并返回,作为结果返回的函数称之为作为值的函数。

示例代码如下:

function outer() {
  var v = 100
  // 在函数的函数体中定义另一个函数 -> 内部(私有)函数
  return function () {
    // 使用匿名函数
    return v * 2
  }
}
var result = outer()
console.log(result) // [Function]

这样做的好处是:

  • 有助于我们确保全局名字空间的纯净性(这意味着命名冲突的机会很小)。
  • 确保私有性 — 这使我们可以选择只将一些必要的函数暴露给“外部世界”,而保留属于自己的函数,使它们不为该应用程序的其他部分所用。

6、闭包

闭包是在函数中提出的概念,简单来说就是一个函数定义中引用了函数外定义的变量,并且该函数可以在其定义环境外被执行。当内部函数以某一种方式被任何一个外部函数作用域访问时,一个闭包就产生了。

实际上闭包可以看做一种更加广义的函数概念。因为其已经不再是传统意义上定义的函数。

闭包的条件:

  • 外部函数中定义了内部函数。
  • 外部函数是具有返回值,且返回值为内部函数。
  • 内部函数还引用了外部函数的变量。

闭包的缺点:

  • 作用域没有那么直观。
  • 因为变量不会被垃圾回收所以有一定的内存占用问题。

闭包的作用:

  • 可以使用同级的作用域。
  • 读取其他元素的内部变量。
  • 延长作用域。
  • 避免污染全局变量

闭包的原理:

我们可以将函数的执行分成两个阶段,即预编译阶段和执行阶段;

  • 在预编译阶段,如果发现内部函数使用了外部函数的变量,它就会在内存中 创建一个闭包对象并保存相对应的值,如果已经存在闭包,则只需要增加对应属性值即可。
  • 在执行完成后,函数执行上下文会被校徽,函数对闭包对象的引用也会被销毁,但其内部函数还持有该闭包的引用,所以内部函数还可以继续使用外部函数的变量

闭包主要是利用作用域链的特性,一个函数内部定义的函数会将包含该函数的活动对象添加到自己本身的作用域链中,函数执行完毕,其执行作用域链销毁,但因内部函数的作用域链仍然引用这个活动对象,所以其活动对象不会被销毁,直到内部函数被销毁后这些活动对象才会被销毁。

闭包的实现的demo:

// 1. 通过返回的内部函数来操作函数中的局部变量
function fun () {
    var v = 100; // 局部变量
    // 通过返回一个对象的方式访问局部变量v 来完成闭包
    return {
        set: function (x) {
            v = x;
        },
        get: function () {
            return v
        }
    }
}
var result = fun();
result.set(200)
console.log(result.get()); // 200
// 2. 定义一个局部变量,计算该函数一共调用几次
var generate_count = function () {
    var container = 0;
    return function () {
        container++
        console.log(`这是第${container}次调用`);
    }
}

var result = generate_count();
result(); // 这是第1次调用
result(); // 这是第2次调用
result(); // 这是第3次调用
// 3.修改 Math.pow() 函数,让求一个数的平方或者立方时,不需要每次传递第二个参数

/*
Math.pow(4, 2) // 求4的平方
Math.pow(4, 3) // 求4的立方
*/

// 写一个函数生成器
function makePower (power) {
    return (number) => {
        return Math.pow(number, power)
    }
}
// 平方
let power2 = makePower(2)
// 立方
let power3 = makePower(3)
// 求4的平方
console.log(power2(4)) // 16
// 求4的立方
console.log(power3(4)) // 62

总结:

本篇文章介绍了JavaScript中的5个高阶函数,分别是递归、回调函数、自调函数、作为值得函数以及闭包的使用以及实现。

到此这篇关于JS 5高阶函数的文章就介绍到这了,更多相关JS 阶函数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 深入学习JavaScript 高阶函数

    高阶函数 高阶函数英文叫 Higher-order function,它的定义很简单,就是至少满足下列一个条件的函数: 接受一个或多个函数作为输入 输出一个函数 也就是说高阶函数是对其他函数进行操作的函数,可以将它们作为参数传递,或者是返回它们. 简单来说,高阶函数是一个接收函数作为参数传递或者将函数作为返回值输出的函数. 函数作为参数传递 JavaScript 语言中内置了一些高阶函数,比如 Array.prototype.map,Array.prototype.filter 和 Array.

  • JavaScript函数式编程(Functional Programming)高阶函数(Higher order functions)用法分析

    本文实例讲述了JavaScript函数式编程(Functional Programming)高阶函数(Higher order functions)用法.分享给大家供大家参考,具体如下: 高阶函数(higher-order functions),就是返回其它函数的函数,或者使用其它函数作为它的参数的函数. 使用函数作为参数 因为函数本身就是一个值,所以可以让函数作为参数传递给其它的函数.JavaScript 有些函数就需要用到函数类型的参数,比如 Array.map. 比如我有一组数据: con

  • 详解JavaScript 高阶函数

    高阶函数简介 高阶函数 的英文名叫 Higher-Order Function ,是 函数式编程 中的一种.他的表现形式往往是通过把函数作为参数传入另一个函数,或者将函数作为另一个函数的返回值返回.在实际开发业务中, 高阶函数往往可以抽象我们的代码 ,将我们的命令式编程转换为复用性更高级的函数式编程,从而 提升我们的代码质量 . 下面拿3个面试中常问的高阶函数举例子,希望看完以后能够提升大家对JS的理解,提高我们的代码质量. chat is cheap,show you my code~ Arr

  • Javascript 常见的高阶函数详情

    目录 一.常见的高阶函数 1.1.filter 1.2.map 1.3.reduce 高阶函数,英文叫 Higher Order function.一个函数可以接收另外一个函数作为参数,这种函数就叫做高阶函数. 示例: function add(x, y, f) { return f(x) + f(y); } //用代码验证一下: add(-5, 6, Math.abs); // 11 一.常见的高阶函数 ES6中数组新增了几种方法,其中 map.reduce.filter 几个都是高阶函数,除

  • JS高阶函数原理与用法实例分析

    本文实例讲述了JS高阶函数原理与用法.分享给大家供大家参考,具体如下: 如果您正在学习JavaScript,那么您必须遇到高阶函数这个术语.这听起来复杂,其实不然. 使JavaScript适合函数式编程的原因是它接受高阶函数. 高阶函数在JavaScript中广泛使用.如果你已经用JavaScript编程了一段时间,你可能已经使用它们甚至不知道. 要完全理解这个概念,首先必须了解函数式编程是什么一等函数(first-Class Function)以及的概念. 函数式编程 在大多数简单的术语中,函

  • 关于JavaScript中高阶函数的魅力详解

    前言 一个函数就可以接收另一个函数作为参数,简言之,函数的参数能够接收别的函数,这种函数就称之为高阶函数 JavaScript 的高阶函数跟 Swift 的高阶函数类似 常见的高阶函数有: Map.Reduce.Filter.Sort 高阶函数是指至少满足下列条件之一的函数 1:函数可以作为参数被传递 2:函数可以作为返回值输出 JavaScript语言中的函数显然的是满足了高阶函数的条件,下面我们一起来探寻JavaScript种高阶函数的魅力. 高阶函数实现AOP AOP(面向切面编程)的主要

  • JS 5高阶函数分享

    目录 1.前言 2.递归 3.回调函数 3.1匿名回调函数 3.2带参数的回调函数 3.3回调函数的优缺点 4.自调函数 5.为值的函数 6.闭包 1.前言 在JavaScript中,函数实际上也是一个数据,也就是说函数也可以赋值给一个变量.本篇文章就来介绍一些JavaScript中的高阶函数的用法. 2.递归 所谓的递归,就是指函数自己调用自己:用一个故事来说呢就是:从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?"从前有座山,山里有座庙,庙里有个老和尚,正在给小和

  • swift 常用高阶函数分享

    map var arr = [1, 2, 3] //map函数是有返回值的,想要arr里面的值map过去需要arr重新接收新值 arr.map { (a : Int) -> Int in return a * 2 } //这种写法只是尾随闭包的简写.. arr = arr.map { $0 * 2 } flatMap //floatMap函数可以降维 var arr1 = [[1, 2], [4, 5], [6, 7]] var aaa = arr1.flatMap { $0 } //float

  • vue常用高阶函数及综合实例

    一. 常用的数组的高阶函数 假设, 现在有一个数组, 我们要对数组做如下一些列操作 找出小于100的数字: 将小于100的数字, 全部乘以2: 在2的基础上, 对所有数求和: 通常我们会怎么做呢? <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> &l

  • 分享5个JS 高阶函数

    目录 1.前言 2.递归 3.回调函数 3.1匿名回调函数 3.2带参数的回调函数 3.3回调函数的优缺点 4.自调函数 5.为值的函数 6.闭包 1.前言 在JavaScript中,函数实际上也是一个数据,也就是说函数也可以赋值给一个变量.本篇文章就来介绍一些JavaScript中的高阶函数的用法. 2.递归 所谓的递归,就是指函数自己调用自己:用一个故事来说呢就是:从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?"从前有座山,山里有座庙,庙里有个老和尚,正在给小和

  • 详谈Python高阶函数与函数装饰器(推荐)

    一.上节回顾 Python2与Python3字符编码问题,不管你是初学者还是已经对Python的项目了如指掌了,都会犯一些编码上面的错误.我在这里简单归纳Python3和Python2各自的区别. 首先是Python3-->代码文件都是用utf-8来解释的.将代码和文件读到内存中就变成了Unicode,这也就是为什么Python只有encode没有decode了,因为内存中都将字符编码变成了Unicode,而Unicode是万国码,可以"翻译"所以格式编码的格式.Python3中

  • Javascript中的高阶函数介绍

    这是一个有趣的东西,这或许也在说明Javascript对象的强大.我们要做的就是在上一篇说到的那样,输出一个Hello,World,而输入的东西是print('Hello')('World'),而这就是所谓的高阶函数. 高阶函数 高阶看上去就像是一种先进的编程技术的一个深奥术语,一开始我看到的时候我也这样认为的. Javascript的高阶函数 然而,高阶函数只是将函数作为参数或返回值的函数.以上面的Hello,World作为一个简单的例子. 复制代码 代码如下: var Moqi = func

  • Javascript 高阶函数使用介绍

    高阶函数(higher-order function)-如果一个函数接收的参数为或返回的值为函数,那么我们可以将这个函数称为高阶函数.众所周知,JavaScript是一种弱类型的语言:JavaScript的函数既不对输入的参数,也不对函数的输出值作强定义和类型检查,那么函数可以成为参数,也可以成为输出值,这就体现了JavaScript对高阶函数的原生支持. 一.参数为函数的高阶函数: function funcTest(f){ //简易判断一下实参是否为函数 if((typeof f)=="fu

  • python利用高阶函数实现剪枝函数

    本文为大家分享了python利用高阶函数实现剪枝函数的具体代码,供大家参考,具体内容如下 案例: 某些时候,我们想要为多个函数,添加某种功能,比如计时统计,记录日志,缓存运算结果等等 需求: 在每个函数中不需要添加完全相同的代码 如何解决? 把相同的代码抽调出来,定义成装饰器 求斐波那契数列(黄金分割数列),从数列的第3项开始,每一项都等于前两项之和 求一个共有10个台阶的楼梯,从下走到上面,一次只能迈出1~3个台阶,并且不能后退,有多少中方法? 上台阶问题逻辑整理: 每次迈出都是 1~3 个台

随机推荐