javascript---我对闭包的理解
一、闭包
闭包是一种特殊的对象。它由两部分构成:函数,以及创建该函数的环境。环境由闭包创建时在作用域中的任何局部变量组成。
如何理解这句话:以一个例子说明;(from MDN)
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
在这个函数中 myFunc就是闭包,因为:1.它是一个函数,2,它的环境是被创建闭时在作用域中的任何局部变量组成(makeFunc函数的局部环境+全局环境+displayName自己的环境)。
作用域补充
http://www.jb51.net/article/30706.htm.
我的总结为:普通函数的作用域包括全局对象,和自己的活动对象(自己的局部都对象)。当函数销毁后,作用域也被销毁。
闭包:将创建它的函数(外部函数)的活动对象添加到自己的作用域链中,更重要的是,此种情况下外部函数执行完毕后,其活动对象不会被摧毁,
因为匿名函数的作用域链仍然在引用这个活动对象(活动对象就会留在内存中)直到该闭包对象被销毁。
二、闭包的应用
摘自MDN (已经验证,一定要敲一遍)我摘写我学到的部分,该文章中的实用的闭包的例子我觉得不适用,没得必要这么用,而且内存一直被占着。虽然占的内存很小。所以闭包还是要尽量不用。
https://developer.mozilla.org/cn/docs/Web/JavaScript/Closures
1.用闭包模拟私有方法
var Counter = (function()
{ var privateCounter = 0;
function changeBy(val) { privateCounter += val; }
return {
increment: function() { changeBy(1); },
decrement: function() { changeBy(-1); },
value: function() { return privateCounter; } } })();
console.log(Counter.value()); /* logs 0 */
Counter.increment();
Counter.increment();
console.log(Counter.value()); /* logs 2 */
Counter.decrement();
console.log(Counter.value()); /* logs 1 */
这样外部无法访问变量
这个地方有个重点是,因为函数自执行了,只有一个执行环境,所以内部的匿名函数共享这个环境。privateCounter,和changeBy方法,只能通过返回的对象里的方法来访问,和操作私有变量和私有方法。模拟私有方法。
2.在循环中创建闭包
直接例子说话:
function createFun(){
var result = new Array();
for (var i =0;i<10;i++){
result[i]=function(){
return i;
};
}
return result;
}
该函数返回的是一个函数数组,每个函数都会返回10,因为每个函数的作用域链中都保存着createFun的活动对象,所以它们引用的都是同一个变量i。此时每个函数都引用着保存变量i的同一个变量,createFun执行后,i=10;
解决方法:
创建一个匿名函数
function createFun(){
var result = new Array();
for (var i =0;i<10;i++){
result[i]=function(num){
return function(){
return num;
}
}(i);
}
return result;
}
能行的原因:1.在createFun中立即执行该匿名函数的结果赋给数组,这里的匿名函数有个参数,参数按值传递。所以就将变量i的当前值复制给num,在匿名函数的内部,又创建并返回了一个访问num的闭包。所以result数组中的每个函数都有自己num变量的一个副本,因此就可以返回各自不同的数值。
3.模拟bind,函数柯里化
ECMAScript5中为函数定义了一个原生的bind方法,由于只支持IE9+、Firefox4+、Chrome所以可以自己利用闭包写一个原生的。
if(!Function.prototype.bind){
//context是函数被绑定的环境
Function.prototype.bind = function(context){
var that = this;
//返回一个闭包,由于闭包能保留外部作用域的引用,在这个例子中就是保留了that
return function (){
return that.apply(context,arguments);
}
}
}
函数柯里化,用于串讲已经设置好了一个或多个参数的函数。
function curry(fn){
//args保留设置好的的参数
var args = Array.prototype.slice.call(arguments,1);
return function (){
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return fn.apply(null,finalArgs);
}
}
function add(num1,num2){
return num1+num2;
}
var curriedAdd = curry(add,5);
alert(curriedAdd(4)); // 9
javascript---我对闭包的理解的更多相关文章
- 讲解JavaScript中对闭包的理解
1.JS中变量的作用域 在理解闭包之前,我们得弄清楚JS中变量的作用域原理,它分为全局作用域和局部作用域,它有一个特点就是局部可以获取全局的声明变量,而全局却不能得到局部声明的变量,我们先来看一个小例 ...
- JavaScript中对于闭包的理解
1.什么是闭包? 闭包,官方对闭包的解释是:一个拥有很多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 闭包的特点: (1).作为一个函数变量的一个引用,当函 ...
- JavaScript面向对象之闭包的理解
首先了解一下什么是闭包,闭包是一个函数,通常被称为闭包函数或者绑定函数,该函数运行在一个特殊的环境里,该环境定义了一些本地变量,当该函数被调用时,仍可以使用这些本地变量. 当一个函数在不位于它所处的环 ...
- [Python]闭包的理解和使用
闭包广泛使用在函数式编程语言中,虽然不是很容易理解,但是又不得不理解. 闭包是什么? 在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包.闭包可以 ...
- JavaScript学习总结——我所理解的JavaScript闭包
一.闭包(Closure) 1.1.什么是闭包? 理解闭包概念: a.闭包是指有权限访问另一个函数作用域的变量的函数,创建闭包的常见方式就是在一个函数内部创建另一个函数,也就是创建一个内部函数,创建一 ...
- 深入理解javascript原型和闭包 (转)
该教程绕开了javascript的一些基本的语法知识,直接讲解javascript中最难理解的两个部分,也是和其他主流面向对象语言区别最大的两个部分--原型和闭包,当然,肯定少不了原型链和作用域链.帮 ...
- 深入理解javascript原型和闭包系列
从下面目录中可以看到,本系列有16篇文章,外加两篇后补的,一共18篇文章.写了半个月,从9月17号开始写的.每篇文章更新时,读者的反馈还是可以的,虽然不至于上头条,但是也算是中规中矩,有看的人,也有评 ...
- 深入理解javascript原型和闭包(1)——一切都是对象
“一切都是对象”这句话的重点在于如何去理解“对象”这个概念. ——当然,也不是所有的都是对象,值类型就不是对象. 首先咱们还是先看看javascript中一个常用的函数——typeof().typeo ...
- 深入理解javascript原型和闭包(2)——函数和对象的关系
上文(理解javascript原型和作用域系列(1)——一切都是对象)已经提到,函数就是对象的一种,因为通过instanceof函数可以判断. var fn = function () { }; co ...
- 深入理解javascript原型和闭包(3)——prototype原型
既typeof之后的另一位老朋友! prototype也是我们的老朋友,即使不了解的人,也应该都听过它的大名.如果它还是您的新朋友,我估计您也是javascript的新朋友. 在咱们的第一节(深入理解 ...
随机推荐
- Airbnb JavaScript Style Guide
Airbnb JavaScript Style Guide() { 用更合理的方式写 JavaScript ES5 的编码规范请查看版本一,版本二. 翻译自 Airbnb JavaScrip ...
- 专访阿里资深研发工程师窦贤明:PG与商业数据库差距并不明显
窦贤明认为, 支持类型.功能和语法丰富,性能优良 9月24日,窦贤明将参加在北京举办的线下活动,并做主题为<Greenplum分片案例分析>的分享.值此,他分享了PG.工作上的一些经历 ...
- MIPS rop gadgets记录贴&&持续更新
前言 本帖记录一些常用的,效果好的 rop gadgets. uClibc 从栈中设置$t9 并跳到 $t9 的gadgets , __thread_start 函数第二行 使用 案例 使用tips: ...
- shiro web 集成
集成方法 shiro与web集成,主要是通过配置一个ShiroFilter拦截所有URL,其中ShiroFilter类似于SpringMVC的前端控制器,是所有请求入口点,负责根据配置(如ini配置文 ...
- html的button疑问
button是可以自动垂直居中的,随便给个高度,它都会自动垂直居中.用控制台查看computed属性里也没有发现和垂直相关的,贴出来希望以后能够了解或有高手看到来解惑小弟:)
- Java中的Number和Math类简单介绍
Java Number类 一般地,当需要使用数字的时候,我们通常使用内置数据类型,如:byte.int.long.double 等. 实例: int a = 5000; float b = 13.65 ...
- 选择 Java 编写 iOS 与 安卓 App的八大理由
[编者按]本文作者为 RoboVM 的 CEO 兼联合创始人 Henric Müller,主要介绍选用 Java 编写移动应用的八大理由.文章系国内 ITOM 管理平台 OneAPM 编译呈现. 在过 ...
- zabbix系列之四——快速使用
https://www.zabbix.com/documentation/3.4/manual/quickstart/login Quickstart 1login and configuring u ...
- leetCode题解之Self Dividing Numbers
1.题目描述 2.题目分析 简单题目,只要挨个判断该数是不是满足条件即可. 3.代码 vector<int> selfDividingNumbers(int left, int right ...
- IPv4到IPv6的三种过渡技术
1. 双协议栈 ( Dual Stack, RFC2893 ) 主机同时运行IPv4和IPv6两套协议栈,同时支持两套协议. 2. 隧道技术 ( Tunnel, RFC2893 ) 这种机制用来在IP ...