我的编程空间,编程开发者的网络收藏夹
学习永远不晚

js中的函数嵌套和闭包详情

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

js中的函数嵌套和闭包详情

前言:

今天就先和大家一起聊一聊我理解的闭包。在聊这个问题之前,先了解一下变量的定义域。
在js中,变量定义域有全局作用域和局部作用域之说。es6中新出现的变量声明关键字,就是为了解决部分变量作用域混乱引入的。全局作用域在这就不谈了。主要说说函数的作用域。

一、作用域

简单一点说,函数的作用域,就是函数的花括号内部,先看两个例子,或许能对这个概念理解的更好一点


function f1(){
  let n = 999
  console.log(n)
}
f1() // 999

function f2(){
  let n = 999
}
alert(n); // 报错

二、函数的返回值

要说闭包之前,我得先说一下函数返回值。关于函数的返回值,小编也是年初才有了一个更深层次的理解。没有返回值的函数,执行之后会返回undefined,有返回值的函数,执行之后就变成了对应的返回值。就像这样


// 没有返回值的函数
function f1(){
  alert(666)
}
console.log(f1()) // 出现弹窗之后,在控制台输出undefind

// 存在返回值
function f2(){
  alert(666)
  return 'over'
}
console.log(f2()) // 出现弹窗之后,在控制台输出over。当然,可以返回字符串,也可以返回Bealon,还可以返回函数。

三、函数嵌套

在《重构——改善既有代码的设计》中,提出了js语法是允许函数内部嵌套函数的,但并不是所有的编程语言都可以的,所谓代码嵌套,就是在函数内部又有函数声明,

就像这样:


function outer(){
  let name = 'lilei'
  function inner(){
    console.log(name)
  }
}  

四、闭包

前面说明了在js中的局部变量作用域的问题,在实际项目中,就是需要在函数外部,访问函数内部的变量,这个时候,按照局部变量作用域的问题。似乎是不可能的,闭包的出现,解决了这个问题。


function outer(){
  let name = 'lilei'
  function inner(){
    return name
  }
  return inner
}

上面是一个典型的闭包函数,在使用这个闭包函数的时候,我们可以这样:


let g = outer()
console.log(g()) // lilei


至此,已经解决了在全局访问函数内的局部变量。但是小编在回家的路上在想,为了实现这个功能,是不是不用这个麻烦,我通过这样的函数,也是可以满足需求的。


function outer(){
  let name = 'lilei'
  return name
}

console.log(outer()) // lilei  


确实上面的代码和通过闭包最终在控制台输出的内容是一样的,那为什么还要引入闭包呢?小编也是想了接近一周才明白的,这就好比变量->函数->类,每层往上都是逐步提升的过程,通过函数可以实现更多的逻辑,比如对数据进行处理,仅仅靠变量是不能实现的。

五、闭包的实际应用

上面小编介绍了闭包,那么在实际项目中有什么应用呢?先看下面代码:

1、隐藏内部变量名称和函数执行暂停


function outer() {
    let name = 1
    function inner() {
        return name ++
    }
    return inner
}
let g = outer()
console.log(g()) // 2
console.log(g()) // 3
console.log(g()) // 4
console.log(g()) // 5

2、setTimeout函数传递参数

默认的setTimeout是这样的:

小编也曾经这样试验过


function f1(p) {
    console.log(p)
}
setTimeout(f1(666),3000) // 并没有延时,直接输出666

要想通过延时来实现对函数传递参数,这时候,闭包的作用就显现出来了。


function f1(a) {
    function f2() {
        console.log(a);
    }
    return f2;
}
var fun = f1(1);
setTimeout(fun,1000); // 一秒之后打印出1

3、回调

  定义行为,然后把它关联到某个用户事件上(点击或者按键)。代码通常会作为一个回调(事件触发时调用的函数)绑定到事件。就像下面这块代码


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试</title>
</head>
<body>
    <a href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  id="size-12">12</a>
    <a href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  id="size-20">20</a>
    <a href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  id="size-30">30</a>

    <script type="text/javascript">
        function changeSize(size){
            return function(){
                document.body.style.fontSize = size + 'px';
            };
        }

        var size12 = changeSize(12);
        var size14 = changeSize(20);
        var size16 = changeSize(30);

        document.getElementById('size-12').onclick = size12;
        document.getElementById('size-20').onclick = size14;
        document.getElementById('size-30').onclick = size16;
</script>
</body>
</html>

4、函数防抖

  在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

   实现的关键就在于setTimeout这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现。就像下面这样:



function debounce(fn,delay){
    let timer = null    //借助闭包
    return function() {
        if(timer){
            clearTimeout(timer) //进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
            timer = setTimeOut(fn,delay) 
        }else{
            timer = setTimeOut(fn,delay) // 进入该分支说明当前并没有在计时,那么就开始一个计时
        }
    }
}

六、使用类实现类似闭包中隐藏内部变量功能

上面是一个关于闭包的实际应用,小编在晚上睡不着觉的时候,想起同样的需求,是不是也可以通过类来实现呢?最后经过一顿折腾,答案是肯定的,就像这样:


class Adder{
    constructor(c){
        this._c = c
    }
    increace(){
        this._c ++ 
    }
    decreace(){
        this._c --
    }
    get finalNum(){
        return this._c
    }
}
let c = new Adder(1)
c.increace()
console.log(c.finalNum) // 2
c.increace()
console.log(c.finalNum) // 3
c.increace()
console.log(c.finalNum) // 4
c.decreace()
console.log(c.finalNum) // 3

参考文章:

https://www.cnblogs.com/gg-qq...

https://www.cnblogs.com/pikac...

https://developer.mozilla.org...

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

js中的函数嵌套和闭包详情

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何使用Python中的内嵌函数和嵌套作用域

如何使用Python中的内嵌函数和嵌套作用域Python是一种功能强大的编程语言,它为开发者提供了许多有用的功能和工具。其中,内嵌函数和嵌套作用域是Python中的两个重要概念。本文将介绍如何使用这些概念,并提供具体的代码示例。在Pytho
如何使用Python中的内嵌函数和嵌套作用域
2023-10-28

c++中函数的定义和调用可以嵌套吗

可以。c++ 允许函数嵌套定义和调用。外部函数可定义内置函数,内部函数可在作用域内直接调用。嵌套函数增强了封装性、可复用性和作用域控制。但内部函数无法直接访问外部函数的局部变量,且返回值类型需与外部函数声明一致,内部函数不能自递归。C++
c++中函数的定义和调用可以嵌套吗
2024-05-06

如何使用Python中的内嵌函数和闭包实现一个计数器

如何使用Python中的内嵌函数和闭包实现一个计数器Python作为一种功能强大的编程语言,提供了很多灵活的工具和技术,使得开发过程变得简单而高效。其中,内嵌函数和闭包是Python中非常重要的概念之一。在本文中,我们将探讨如何利用这两个概
2023-10-22

基于Python函数的作用域规则和闭包(详解)

作用域规则 命名空间是从名称到对象的映射,Python中主要是通过字典实现的,主要有以下几个命名空间: 内置命名空间,包含一些内置函数和内置异常的名称,在Python解释器启动时创建,一直保存到解释器退出。内置命名实际上存在于一个叫__bu
2022-06-04

Python中的闭包和匿名函数有什么区别

闭包和匿名函数都是函数的概念,但是它们有一些区别:闭包是指在一个函数内部定义另一个函数,并且内部函数可以访问外部函数的变量。闭包通常用于保护变量,避免被外部函数修改。而匿名函数是指没有名字的函数,通常用于一次性的简单操作。闭包是由一个函数和
Python中的闭包和匿名函数有什么区别
2024-03-12

C++ 函数中闭包的优点和缺点是什么?

闭包是一种嵌套函数,它能访问外层函数作用域的变量,优点包括数据封装、状态保持和灵活性。缺点包括内存消耗、性能影响和调试复杂性。此外,闭包还可以创建匿名函数,并将其作为回调或参数传递给其他函数。C++ 函数中闭包的优点和缺点闭包是指一个嵌套
C++ 函数中闭包的优点和缺点是什么?
2024-04-25

函数指针和闭包在Golang中的应用场景

函数指针在 go 中用于函数回调、延迟执行和多态性。闭包用于状态管理、事件处理和延迟初始化。函数指针和闭包在 Go 中的应用场景函数指针函数指针是指向函数的变量。可以使用 func 关键字声明函数指针类型:type Fn func(in
函数指针和闭包在Golang中的应用场景
2024-04-15

PHP 匿名函数和闭包在数据结构中的应用

匿名函数和闭包在数据结构处理中的应用php 中的匿名函数和闭包可用于处理数组、链表和队列等数据结构。针对数组,匿名函数可用于过滤元素;针对链表,闭包可用于创建节点;针对队列,匿名函数和闭包可实现 fifo 队列操作。这些工具提供简洁、可重用
PHP 匿名函数和闭包在数据结构中的应用
2024-05-07

如何高效利用Golang中的函数指针和闭包

使用函数指针和闭包可以高效地管理回调和创建通用过滤器。函数指针指向函数,而闭包捕获其创建环境,允许访问外部变量。它们可以简化代码,但开销可能高于直接函数调用。在避免创建匿名函数或需要通用过滤时,利用函数指针和闭包的灵活性可以提高性能。如何高
如何高效利用Golang中的函数指针和闭包
2024-04-15

函数指针和闭包在Golang web开发中的案例

函数指针和闭包在 go web 开发中的应用:函数指针:允许动态更改调用的函数,提高灵活性。解耦代码,简化维护。实战案例:处理 http 路由,将控制器处理程序绑定到不同的路由。闭包:访问创建范围之外的变量,捕获数据。实战案例:创建私有数据
函数指针和闭包在Golang web开发中的案例
2024-04-16

golang匿名函数和闭包在Web开发中的应用

在 go 中,匿名函数和闭包可提高代码的可读性、可重用性和灵活性。匿名函数是无需定义名称的函数,而闭包包含对外部作用域变量的引用。在 web 开发中,我们可以使用匿名函数和闭包创建可重用的 http 请求处理程序,从而简化代码并提高维护性。
golang匿名函数和闭包在Web开发中的应用
2024-05-02

golang匿名函数和闭包在并发编程中的作用

在并发编程中,匿名函数和闭包通过创建拥有独立状态的代码块来发挥重要作用。它们用于:1. 创建协程 2. 传递状态 3. 实现并发控制。例如,我们可以使用匿名函数创建 goroutine 以实现并发,并使用闭包来实现共享数据的自定义计数器。通
golang匿名函数和闭包在并发编程中的作用
2024-05-03

函数指针和闭包在分布式系统中的使用

函数指针和闭包在分布式系统中拥有广泛的应用,它们分别支持运行时的动态函数调用和跨线程/进程的数据共享。在分布式任务处理中,函数指针可用于任务调度,闭包可用于任务执行,提升系统的灵活性与效率。函数指针和闭包在分布式系统中的使用函数指针和闭包
函数指针和闭包在分布式系统中的使用
2024-04-16

函数指针和闭包在Golang单元测试中的应用

在 go 单元测试中,函数指针和闭包可以帮助创建更灵活、可读性更高的代码。函数指针:引用函数的指针变量,允许将函数作为参数传递或存储在数据结构中。闭包:由函数及其作用域中数据的引用组成的组合,用于捕获局部变量并创建状态特定的测试场景。函数指
函数指针和闭包在Golang单元测试中的应用
2024-04-16

golang匿名函数和闭包在学习和教学中的最佳实践

在 go 语言中,匿名函数是无名称的一次性函数,用于定义临时执行块,而闭包则是带有自由变量(来自外部作用域,可在函数体内使用的变量)的函数。学习最佳实践包括保持匿名函数简短,明智地使用闭包,并充分利用其优势,但避免过度使用。在教学中,从简单
golang匿名函数和闭包在学习和教学中的最佳实践
2024-04-30

编程热搜

目录