闭包

JS闭包各种坑

守給你的承諾、 提交于 2019-11-28 07:39:43
闭包是js开发惯用的技巧,什么是闭包? 闭包指的是:能够访问另一个函数作用域的变量的函数 。清晰的讲:闭包就是一个函数,这个函数能够访问其他函数的作用域中的变量。eg: function outer() { var a = '变量1' var inner = function () { console.info(a) } return inner // inner 就是一个闭包函数,因为他能够访问到outer函数的作用域 } 很多人会搞不懂匿名函数与闭包的关系,实际上,闭包是站在作用域的角度上来定义的,因为inner访问到outer作用域的变量,所以inner就是一个闭包函数。虽然定义很简单,但是有很多坑点,比如this指向、变量的作用域,稍微不注意可能就造成内存泄露。我们先把问题抛一边,思考一个问题: 为什么闭包函数能够访问其他函数的作用域 ? 从堆栈的角度看待js函数   基本变量的值一般都是存在栈内存中,而对象类型的变量的值存储在堆内存中,栈内存存储对应空间地址。基本的数据类型: Number 、Boolean、Undefined、String、Null。 var a = 1 //a是一个基本类型 var b = {m: 20 } //b是一个对象 对应内存存储: 当我们执行 b={m:30}时,堆内存就有新的对象{m:30},栈内存的b指向新的空间地址( 指向{m:30}

闭包的使用场景

别说谁变了你拦得住时间么 提交于 2019-11-28 07:29:06
一、闭包   由于在Javascript语言中,只有函数内部的子函数才能读取局部变量, 闭包就是能够读取其他函数内部变量的函数 。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。   比如下面的代码: function f1() { var n = 999; function f2() { console.log(n); } return f2; } var result = f1(); result();//999   函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。   这就是Javascript语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以, 父对象的所有变量,对子对象都是可见的 ,反之则不成立。   既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,就可以在f1外部读取它的内部变量了。 二、闭包的使用场景 1.setTimeout    原生的setTimeout传递的第一个函数不能带参数,通过闭包可以实现传参效果。 function f1(a) { function f2() { console.log(a); } return f2; } var fun = f1(1); setTimeout(fun

关于 C# 闭包

久未见 提交于 2019-11-28 06:24:18
通过Lambda 表达式可以访问 Lambda 表达式外部的变量 , 这种行为可称之为闭包 , 下面例子所示: Lambda 表达式访问一个外部变量 Warning, 同时外部的Warning变量修改其内容, 下面 task启动时, 将输出字符串 "张三允许入内" 对于一个被捕获的变量, 只要还有任何委托实例引用它, 那么它将一直存在, 外部访问会影响委托的输出, 委托中进行修改同样会将这个外部变量更改。 总结: 当一个变量被捕获时, 那么捕捉的时变量的 "实例" 捕获的变量的生存周期被延长, 和捕捉它的委托一样长。 多个委托可以捕获同一个变量 , 该变量影响不同的委托的输出。 必要情况创建额外的类型来保存捕获变量。 来源: https://www.cnblogs.com/zh7791/p/11397200.html

JavaScript性能优化

痴心易碎 提交于 2019-11-28 05:43:54
如今主流浏览器都在比拼JavaScript引擎的执行速度,但最终都会达到一个理论极限,即无限接近编译后程序执行速度。 这种情况下决定程序速度的另一个重要因素就是代码本身。 在这里我们会分门别类的介绍JavaScript性能优化的技巧,并提供相应的测试用例,供大家在自己使用的浏览器上验证, 同时会对特定的JavaScript背景知识做一定的介绍。 目录 变量查找优化 变量声明带上var 慎用全局变量 缓存重复使用的全局变量 避免使用with 核心语法优化 通过原型优化方法定义 避开闭包陷阱 避免使用属性访问方法 避免在循环中使用try-catch 使用for代替for…in…遍历数组 使用原始操作代替方法调用 传递方法取代方法字符串 脚本装载优化 使用工具精简脚本 启用Gzip压缩 设置Cache-Control和Expires头 异步加载脚本 DOM操作优化 减少DOM元素数量 优化CSS样式转换 优化节点添加 优化节点修改 减少使用元素位置操作 避免遍历大量元素 事件优化 使用事件代理 动画优化 设置动画元素为absolute或fixed 使用一个timer完成多个元素动画 变量查找优化 变量声明带上var 1. 如果声明变量忘记了var,那么js引擎将会遍历整个作用域查找这个变量,结果不管找到与否,都是悲剧。 如果在上级作用域找到了这个变量,上级作用域变量的内容将被无声的改写

POJ 2594 (传递闭包 + 最小路径覆盖)

主宰稳场 提交于 2019-11-28 05:16:06
题目链接: POJ 2594 题目大意: 给你 1~N 个点, M 条有向边。问你最少需要多少个机器人,让它们走完所有节点,不同的机器人可以走过同样的一条路,图保证为 DAG。 很明显是 最小可相交路径覆盖 问题。要先通过闭包建图后,再当作 最小不可交路径覆盖 问题 求解即可。 原因: 与 最小不可交路径覆盖 问题不同的是,两个机器人可以走相同的边,在最小覆盖的基础上如果还要走过相同的边,那么说明后一个机器人到达某一个未被走过的节点时,必须要经过某一条路,即已经走过的这条路。那么我们用闭包传递一下,在 A 能到达 B 点的情况下,直接建 A ---> B ,即表示 A 能走到 B ,这样就不必要再走那条重复的路径。而又在 最小不可交路径覆盖 问题上,连接 Ax 与 By ,使得变成二分图。 代码如下: #include<iostream> #include<algorithm> #include<string.h> #define maxn 508 using namespace std; int n,m,cnt; int head[maxn],c[maxn]; bool flag[maxn][maxn],vis[maxn]; struct Edge { int to; int next; }edge[maxn*maxn*2];4387596 inline void add(int

谈谈装饰器的实现原理

不问归期 提交于 2019-11-28 05:08:46
关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android、Python、Java和Go,这个也是我们团队的主要技术栈。 Github:https://github.com/hylinux1024 微信公众号:终身开发者(angrycode) 谈谈装饰器(Decorator)的实现原理 熟悉 Java 编程的程序猿对 装饰器模式 一定不陌生,它是能够动态的给一个类添加新的行为的一种设计模式。相对于通过继承的方式使用装饰器会更加灵活。 在 Python 里面装饰器( Decorator )也是一个非常重要的概念。跟装饰器模式类似,它 能够动态为一个函数、方法或者类添加新的行为 ,而不需要通过子类继承或直接修改函数的代码来获取新的行为能力,使用 Decorator 的方式会更加 Pythonic 。 要理解 装饰器 我们就要从函数说起。 0x00 函数 在 Python 中函数是作为一级对象存在的(一切都是对象),它拥有自己的属性,函数名可以赋值给一个变量,也可以作为另一个函数的参数进行传递。 1、定义函数 def fib(n): """打印小于 n 的 fibonacci 数列""" a, b = 0, 1 while a < n: print(a, end=' ') a, b = b, a + b print() def call

匿名函数和闭包的区别

半世苍凉 提交于 2019-11-28 04:34:42
在学习python基础中对于匿名函数和闭包等只是有不太明白的地方,分不清他们的区别,所以整理下方便后期复习提升。反思:对于零碎的python基础知识,一定要牢记,多看多敲代码,一回生二回熟,熟能生巧。 一、匿名函数 所谓匿名就是不需要函数表达式 lambda x : x*x 关键字lambda表示匿名函数,冒号前面的x表示函数参数。 匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。 小结: 匿名函数:lambda表达式:通过一个表达式实现函数功能 基本语法:lambda 参数列表:表达式语句 参数列表:用来给表达式传递数据 表达式语句:计算表达式,计算结果会自动输出 注意事项:lambda表达式,主要是用来替代功能简单的函数的!提高代码的简洁性 不要滥用!大量使用lambda表达式会造成代码可读性的严重下降! 二、闭包 1、定义:内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数。 2、创建闭包函数:    如果在一个 内部函数里对外部作用域 (但不是全局作用域)的变量 进行引用 ,内部函数称为闭包(closure) ------闭包函数必须有内嵌函数 ------内嵌函数需要引用该嵌套函数上一级namespace中的变量 ------闭包函数必须返回内嵌函数 小结: 闭包就是函数里面嵌套一个函数 因为函数的出现

第18课 捕获机制及陷阱

穿精又带淫゛_ 提交于 2019-11-28 03:51:13
一. C++14的捕获方式 (一)3种捕获方式:   1. 按值捕获 : [=]或[var],前者为按值的默认捕获方式   2. 按引用捕获 :[&]或[&var],前者为按引用的默认捕获方式   3. 移动捕获 : 见后面的《广义捕获》 (二) 默认捕获方式的陷阱 : [=]和[&]   1.按引用捕获会导致闭包(由lambda表达式创建的对象)中包含 指向局部对象或形参的引用 。一旦该 闭包超出该局部变量或形参的生命期 ,那么闭包内的引用就会发生 “引用空悬” 。当然 如果闭包和局部变量/形参的生命期相同,就不会现这个问题 。   2. 按值的默认捕获 极易受 空悬指针 影响(尤其是this),并且会让人 产生lambda表达式是独立的、不受外界影响的错觉 。 【编程实验】默认捕获方式的陷阱 #include <iostream> #include <vector> #include <memory> #include <functional> using namespace std; using FilterContainer = std::vector < std::function<bool(int)>>; //筛选函数的容器 FilterContainer filters; //1. 按引用捕获造成的“引用悬空”问题 void addDivisorFilter() {

01

∥☆過路亽.° 提交于 2019-11-28 03:39:20
01:求结果 def multipliers(): return [lambda x:i*x for i in range(4)] print([m(2) for m in multipliers()]) def a(): return [lambda x:i*x for i in range(4)] b=a() #返回个列表函数 # b[2](1) print(b[1](1)) # print(type(b),b) print([m(1) for m in a()]) print([i*i for i in [1,2,3]]) [3, 3, 3, 3] [1, 4, 9] ''' def multipliers(): return [lambda x:i*x for i in range(4)] print([m(2) for m in multipliers()]) #解释:   函数返回值为一个列表表达式,经过4次循环结果为包含四个lambda函数的列表, 由于函数未被调用,循环中的i值未被写入函数,经过多次替代,循环结束后i值为3, 故结果为:6,6,6,6 func=lambda x:x+1 print(func(1)) #2 print(func(2)) #3 #以上lambda等同于以下函数 def func(x): return(x+1) ''' 拓展: def

javascript进阶系列专题:闭包(Closure)

混江龙づ霸主 提交于 2019-11-28 02:27:22
在javascript中,函数可看作是一种数据,可以赋值给变量,可以嵌套在另一个函数中。 var fun = function(){ console.log("平底斜"); } function fun(){ var n=10; function son(){ n++; } son(); console.log(n); } fun(); //11 fun(); //11 我们把上面第二段代码稍微修改下: var n=10; function fun(){ function son(){ n++; } son(); console.log(n); } fun(); //11 fun(); //12 看出差别了吗,如果理解不了代码执行结果,请看上一篇博文,关于javascript作用域和作用域链的讲解。 上面这段代码中变量n是全局变量,随时可能被重新赋值,而无需通过fun函数的调用。为了让变量n不受污染,或者说是减少全局变量的污染,我们需要把n放到函数中作为局部变量。 function fun(){ var n=10; function son(){ n++; console.log(n); } son(); } fun(); //11 fun(); //11 如果我们可以在全局中直接调用son函数,那么便可以达成想要的效果。son函数现在是作为局部变量存在,要想在全局中访问