02函数-03-闭包

1、闭包的概念

闭包是一种特殊的程序结构,即 函数A中定义了另一个函数a,内部函数a引用了外部函数A的参数和局部变量,最终A会返回一个保存了相关参数和变量的函数a。

简洁地说,外层函数将保存了信息的可执行内层函数作为结果返回

来看个例子:
//求和功能  
function lazy_sum(arr) {var sum = function () {return arr.reduce(function (x, y) {return x + y;});}return sum;
}
//当调用该函数时不会直接返回结果,而是返回函数 --e.g.--> // var f = lazy_sum([1, 2, 3, 4, 5]); --> 得到 function sum()
//调用函数时,才得到真正的结果 --e.g.--> // f(); --> 得到 15
//另,即使传入相同参数的两个函数A,返回的函数a也是不同的
12
1
//求和功能  
2
function lazy_sum(arr) {
3
    var sum = function () {
4
        return arr.reduce(function (x, y) {
5
            return x + y;
6
        });
7
    }
8
    return sum;
9
}
10
//当调用该函数时不会直接返回结果,而是返回函数 --e.g.--> // var f = lazy_sum([1, 2, 3, 4, 5]); --> 得到 function sum()
11
//调用函数时,才得到真正的结果 --e.g.--> // f(); --> 得到 15
12
//另,即使传入相同参数的两个函数A,返回的函数a也是不同的

2、闭包的小坑

闭包的返回函数,是没有立刻执行的,直到调用该函数才会执行,这意味着,如果是引用了循环变量,会变成如下情况:
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];//然而f1(),f2(),f2()的结果并不是1,4,9,而全部是16
16
1
function count() {
2
    var arr = [];
3
    for (var i=1; i<=3; i++) {
4
        arr.push(function () {
5
            return i * i;
6
        });
7
    }
8
    return arr;
9
}
10
11
var results = count();
12
var f1 = results[0];
13
var f2 = results[1];
14
var f3 = results[2];
15
16
//然而f1(),f2(),f2()的结果并不是1,4,9,而全部是16

原因就在于返回的函数引用了变量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];f1(); // 1
f2(); // 4
f3(); // 9
20
1
function count() {
2
    var arr = [];
3
    for (var i=1; i<=3; i++) {
4
        arr.push((function (n) {
5
            return function () {
6
                return n * n;
7
            }
8
        })(i));
9
    }
10
    return arr;
11
}
12
13
var results = count();
14
var f1 = results[0];
15
var f2 = results[1];
16
var f3 = results[2];
17
18
f1(); // 1
19
f2(); // 4
20
f3(); // 9
这里用到了一个语法 “创建一个匿名函数并立即执行”:
(function (x) {return x * x;
})(3); // 9
//由于JavaScript语法解析的问题,会报SyntaxError错误,因此需要用括号把整个函数定义括起来
4
1
(function (x) {
2
    return x * x;
3
})(3); // 9
4
//由于JavaScript语法解析的问题,会报SyntaxError错误,因此需要用括号把整个函数定义括起来

3、闭包的意义

上面我们讲到,闭包相当于把传参后的函数进行了保存但是并不会立刻执行,你要调用返回的这个函数才会执行,所以说闭包的意义只是在于延迟执行函数吗?当然不完全是这样,还有其他很多功能。

在例如Java中,我们要封装一个私有变量,只需要加上private关键字就可以了,可是在JS中,我们也想要封装一个私有变量,怎么办?利用闭包。
//e.g.创建一个计数器
function create_counter(initial) {var x = initial || 0;return {inc: function () {x += 1;return x;}}
}
10
1
//e.g.创建一个计数器
2
function create_counter(initial) {
3
    var x = initial || 0;
4
    return {
5
        inc: function () {
6
            x += 1;
7
            return x;
8
        }
9
    }
10
}

闭包中携带了局部变量x,但是当你使用该函数时,你实际上是无法访问到变量x的,即实际上这个函数的状态完全被隐藏了:
var c1 = create_counter();
c1.inc(); // 1
c1.inc(); // 2
c1.inc(); // 3var c2 = create_counter(10);
c2.inc(); // 11
c2.inc(); // 12
c2.inc(); // 13
9
1
var c1 = create_counter();
2
c1.inc(); // 1
3
c1.inc(); // 2
4
c1.inc(); // 3
5
6
var c2 = create_counter(10);
7
c2.inc(); // 11
8
c2.inc(); // 12
9
c2.inc(); // 13

闭包还可以创建新函数,例如把多参数的函数变成单参数的函数。例如,要计算x的y次方可以用Math.pow(x, y)函数,不过考虑到经常计算x平方或x立方,我们可以利用闭包创建新的函数pow2和pow3:
function make_pow(n) {return function (x) {return Math.pow(x, n);}
}// 创建两个新函数:
var pow2 = make_pow(2);
var pow3 = make_pow(3);pow2(5); // 25
pow3(7); // 343
x
1
function make_pow(n) {
2
    return function (x) {
3
        return Math.pow(x, n);
4
    }
5
}
6
7
// 创建两个新函数:
8
var pow2 = make_pow(2);
9
var pow3 = make_pow(3);
10
11
pow2(5); // 25
12
pow3(7); // 343


转载于:https://www.cnblogs.com/deng-cc/p/6622610.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/429472.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mapper同时添加数据只能添加一条_springcloud项目搭建第二节:eureka+数据库

在上一节搭建的项目基础上&#xff0c;在父项目spring-cloud的pom文件中添加mapper启动器和mysql驱动的配置&#xff0c;如果项目中使用lombok也可以引用&#xff0c;这里需要注意的是lombok引用的配置不在dependencyManagement结构中&#xff0c;这时为什么呢&#xff0c;因为…

C#控件命名规范

类 型 前 缀 示 例 Adrotator adrt adrtTopAd BulletedList blst blstCity Button btn btnSubmit Calendar cal calMettingDates CheckBox chk chkBlue CheckBoxList chkl chklFavColors DropDownList drop dropCountries FileUpLoad fup fupImage …

在centOS7.2里安装virtualenv和flask

1&#xff09; 安装pip工具 #wget https://bootstrap.pypa.io/get-pip.py #python get-pip.py 2&#xff09; 安装virtualenv&#xff0c;并创建一个开发环境 #pip install virtualenv #mkdir rongtangzi #创建一个项目 #cd rongtangzi #virtualenv env1 #…

事务连接中断_一文搞懂分布式事务-CAP理论

互联网系统中&#xff0c;分布式事务是无法避免的&#xff0c;目前多数解决方案是BASE理论&#xff0c;最终一致性&#xff0c;结合事务补偿。1.什么是CAP理论。CAP理论&#xff0c;又称为布鲁尔定理&#xff0c;是加州大学伯克利分校的计算机科学家埃里克.布鲁尔(Eric Brewer)…

C# WinForm中获取当前程序运行目录的方法

C# WinForm中获取当前程序运行目录的方法&#xff1a; “AppDomain.CurrentDomain.BaseDirectory”:获取当前应用程序所在目录的路径&#xff0c;最后包含“\”&#xff1b;“System.Threading.Thread.GetDomain().BaseDirectory”:获取当前应用程序所在目录的路径&#xff0c…

网络攻防 第四周学习总结

教材学习内容总结 第四章主要介绍了网络嗅探和协议分析网络嗅探是一种常用的窃听技术&#xff0c;它利用计算机的网络接口截获目的地为其他计算机的数据报文&#xff0c;以监听数据流中所包含的用户账户密码或私密信息等。 网络嗅探具有很强的隐蔽性&#xff0c;往往让网络信息…

获取内存_如何获取一个进程所占用的内存

推荐观看&#xff1a;BATJ面试官最喜欢问的&#xff1a;多线程、线程并发面试题详解&#xff08;volatileThreadLocalSleep&#xff09;_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com通过 ps 可以获知一个进程所占用的内存$ ps -O rss -p 3506PID RSS S TTY …

461. Hamming Distance【数学|位运算】

2017/3/14 15:23:55 The Hamming distance between two integers is the number of positions at which the corresponding bits are different. Given two integers x and y, calculate the Hamming distance. 题目要求&#xff1a;求两个数字二进制位中同一位置不同bit的个数…

中的ama格式_想发SCI?期刊引用格式选好了没?

我~芳~老师~又回来开坑了哈哈哈哈哈&#xff01;&#xff01;&#xff01;对于一心想要冲向SCI、EI顶峰&#xff0c;拉都拉不住的同学来说&#xff0c;我们需要把论文中的每一个细节都抠得死死的。合乎规范地引用科学期刊&#xff08;Scientific Journal&#xff09;绝对是最重…

着陆攻击LAND Attack

着陆攻击LAND Attack着陆攻击LAND Attack也是一种拒绝服务攻击DOS。LAND是Local Area Network Denial的缩写&#xff0c;意思是局域网拒绝服务攻击&#xff0c;翻译为着陆攻击只是一种错误的理解。攻击原理为&#xff0c;攻击机向目标机发送一个SYN的TCP包&#xff0c;包中的源…

伺服怎么接单相220伏_乐利网带你认识伺服电机及工作原理

什么是伺服电机&#xff0c;应该听过人的不少&#xff0c;没听过的也占不少数&#xff0c;其实&#xff0c;伺服电机是指在伺服系统中控制机械元件运转的发动机&#xff0c;是一种补助马达间接变速装置。伺服电机可使控制速度&#xff0c;位置精度非常准确&#xff0c;可以将电…

BZOJ 1877 拆点费用流

思路&#xff1a; 呃 水题不解释 行么,, //By SiriusRen #include <queue> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define mem(x,y) memset(x,y,sizeof(x)) const int N88888,M444; int n,m,xx,yy,zz,edg…

插入始终是1_OneNote使用小记(1)——针对PPT做笔记及最合适的PPT插入方式

本人经常使用OneNote进行上课笔记的记录&#xff0c;本文大概总结一下我是如何在上课时针对PPT进行笔记记录的&#xff0c;以及非常重要的PPT插入所占空间的问题。设备&#xff1a;普通笔记本电脑&#xff0c;无触控&#xff0c;故不使用绘图功能软件&#xff1a;OneNote2016&a…

Cocos2dx 3.11版本 视频添加跳过按钮

最近比较忙&#xff0c;这里不写原理只写代码&#xff0c;以后再补。 目前跨平台处理&#xff0c;只在Android和ios实现。其他平台暂时未加。 1.frameworks/cocos2d-x/cocos/ui/UIVideoPlayer.h 添加一个函数 virtual void addSkipButton(); 2.在ios和Android实现的地方实现以…

有效数据外含有额外数据_Excel|应用数据有效性规范数据录入

【问题】EXCEL输入数据时&#xff0c;经常会输入不规范或者无效的数据&#xff0c;对数据的统计工作带来很大的麻烦。数据验证能够建立特定的规则&#xff0c;限制单元格可以输入的内容&#xff0c;从而规范数据输入&#xff0c;提高数据统计与分析效率。数据验证&#xff0c;在…

怎么实现hover_web前端CSS实现一个粒子动效的按钮

按钮(button)可能是网页中最常见的组件之一了&#xff0c;大部分都平淡无奇&#xff0c;如果你碰到的是一个这样的按钮&#xff0c;会不会忍不住多点几次呢&#xff1f;通常这类效果第一反应可能就是借助canvas了&#xff0c;比如下面这个案例点击预览(建议去codepen原链接点击…

BZOJ 2242: [SDOI2011]计算器 [快速幂 BSGS]

2242: [SDOI2011]计算器 题意&#xff1a;求\(a^b \mod p,\ ax \equiv b \mod p,\ a^x \equiv b \mod p\)&#xff0c;p是质数 这种裸题我竟然WA了好多次 第三个注意判断a和b整除p的情况 #pragma GCC optimize ("O2") #include <iostream> #include <cstdio…

获取某一列_Excel VBA 8.2 获取多列唯一值,不用肉眼,VBA帮你快速搞定

前景提要(文末提供源码下载)昨天我们学习了针对单列的数据进行获取唯一值的方法&#xff0c;今天我们提升下难度&#xff0c;来尝试下获取已多列为参照物&#xff0c;获取唯一值的方法&#xff0c;昨天有很多小伙伴说还可以用字典的方法更加的简单&#xff0c;其实&#xff0c;…

python求众数代码_python-LeetCode-求众数

题目&#xff1a;给定一个大小为 n 的数组&#xff0c;找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的&#xff0c;并且给定的数组总是存在众数。示例 1:输入: [3,2,3]输出: 3示例 2:输入: [2,2,1,1,1,2,2]输出: 2众数——众数(Mode)…

dataoutputstream.write 有时无法发送_RTK实操——CORS官方网教您如何解决RTK无法固定的问题...

测量员在日常测量工作中&#xff0c;非常期盼都能“固定解”&#xff0c;特别是是在密林、高楼下接收信号-测定位置-收工绘图&#xff0c;一整套流程跑完&#xff0c;就稳妥了。然而事与愿违&#xff0c;在使用过程中&#xff0c;有时候会遇到各种各样的复杂状况&#xff0c;导…