接触过javascript的人应该听过闭包(closure),有一种观点认为是闭包赋予了javascript的强大能力,也赋予了它具备OOP的特征。既然javascript closure如此重要,那么问题来了,什么是closure呢?closure有什么作用?本文将结合我自己对closure的理解,用尽量通俗易懂的方式来进行阐述。

  先看看老外对closure怎么定义的?A closure is an inner function that has access to the outer (enclosing) function's variables—scope chain.从字面上来看,可以翻译为:闭包就是一个内部函数,它具备访问外部函数变量(这些变量位于作用域链中)的能力[注意变量不包含this和arguments]。但这个概念还是过于“专业化”, 不接地气,只从概念上来看,非常抽象。下面用一段JS来对应解释闭包的概念:

个人理解为:fInner函数定义在fOuter的内部,可以访问fOuter定义的变量,这个fInner函数就是closureclosure的 scope chain有3个一个是fInner函数定义的变量;一个是外部fOuter的变量;还有一个是全局变量(global variables)。closure的作用可以保留变量的值换句话说,函数fInner就是一个closure

  closure可以干2件事情:

  1)closure可以调用(闭包存储的外部变量是引用而不是值,这点非常重要)在当前函数以外的定义的变量(即使外部函数已经返回);

  2)closure可以修改外部定义的变量值

下面通过一段JS代码来阐述为什么闭包存储的外部变量是引用而不是值,这点非常重要

     function mixFunction(a)
{
var result=[],i,n;
n=a.length;
for(i=0;i<n;i++){
result[i]=function(){
//Closure对外部变量是引用
console.log("for i="+i);
return a[i];//a[i-1]
}
}
return result;
}
var mixcall=mixFunction([10,20,30]);
var f=mixcall[0];
console.log(f());//?应该输出什么值

f()会输出 10 么?答案是undefined!!!

为什么是这样的呢? 因为闭包对i是引用,在for循环时,会不断更新i的值。即在调用f()后,i已经被修改为3 (i===3),而a[3]为undefined!!

上述的代码始终会输出a[2]的值,也就是30。

那么问题来了?怎么解决该问题呢?这就要用到JS中的IIFE技术啦!IIFE技术来解决JS缺少块级作用域的解决方案。如下代码所示:

     function mixFunctionFix(a)
{
var result=[],i,n;
n=a.length;
for(i=0;i<n;i++){
//IIFE技术来解决JS缺少块级作用域的解决方案
(function(j){
result[i]=function(){
//Closure对外部变量是引用
console.log("for j="+j);
return a[j];
}
})(i)
}
return result;
}
var mixcall=mixFunctionFix([10,20,30]);
var f=mixcall[0];
console.log(f());//

前面提到JS闭包可以实现OOP的特征,下面给出JS如何定义一个“User类”(实际是一个JS函数)。此函数有私用变量和方法,同时也具有公开的方法。私有变量和方法不能函数外部调用:

     function User(){
//private properties
var _name = '';
var _age = 0; //private method
function privateMethod(){
return "private Method"
};
//public method
this.setName = function(name){
//can call
privateMethod();
_name = name;
return this;
}; this.setAge = function(age){
_age = age;
return this;
};
this.getAge = function(){
return _age;
};
this.getName = function(){
return _name;
};
}
var p=new User();
console.log(p.setName('jackwang').setAge(28));
console.log(p.getName());//jackwang
console.log(p.getAge());//
console.log(p._name);//undefined
console.log(p.privateMethod());//error

私有变量_name和_age以及私有方法privateMethod()都不能在函数外部调用。User设置name和age只能通过公开方法setName和setAge进行,获取只能通过getName和getAge进行访问。

有人会问,这个是闭包么?看下图:

如何理解javascript closure ?的更多相关文章

  1. 【转】深入理解JavaScript闭包闭包(closure) (closure)

    一.什么是闭包?"官方"的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述 ...

  2. 理解Javascript 的闭包(closure)

    要理解闭包的概念先从变量的作用域说去 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之 ...

  3. 深入理解JavaScript的闭包特性如何给循环中的对象添加事件

    初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...

  4. 深入理解JavaScript闭包【译】

    在<高级程序设计>中,对于闭包一直没有很好的解释,在stackoverflow上翻出了一篇很老的<JavaScript closure for dummies>(2016)~ ...

  5. (转)深入理解JavaScript 模块模式

    深入理解JavaScript 模块模式 (原文)http://www.cnblogs.com/starweb/archive/2013/02/17/2914023.html 英文:http://www ...

  6. 深入理解javascript的闭包

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域 ...

  7. 深入理解javascript闭包(一)

    闭包(closure)是Javascript语言的一个难点.也是它的特色,非常多高级应用都要依靠闭包实现. 一.什么是闭包? 官方"的解释是:闭包是一个拥有很多变量和绑定了这些变量的环境的表 ...

  8. 深入理解javascript闭包(一)

    原文转自脚本之家(http://www.jb51.net/article/24101.htm) 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. ...

  9. 深入理解Javascript闭包概念

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部能够直接读取全局变量 ...

随机推荐

  1. CSS中模拟父元素选择器

    很多情况下,我们需要找到父元素,但可惜的是css中并没有这样的一个选择器. 至于原因可以看张鑫旭的如何在CSS中实现父选择器效果这篇文章. 简单来说这个实现并不是真正的父元素选择器,只是利用其它思路来 ...

  2. wangEditor——轻量级web富文本框

    提示:最新版wangEditor请参见  http://www.wangeditor.com/  和   https://github.com/wangfupeng1988/wangEditor 交流 ...

  3. KendoUI系列:Window

    1.基本使用 <link href="@Url.Content("~/Content/kendo/2014.1.318/kendo.common.min.css") ...

  4. OpenCascade Tcl vs. ACIS Scheme

    OpenCascade Tcl vs. ACIS Scheme eryar@163.com 摘要Abstract:本文通过OpenCascade的Tcl/Tk和ACIS的Scheme的对比来说明脚本语 ...

  5. 参与github上开源项目的大致流程和注意事项

    Foreword github是一个很火的代码托管服务网站,可能好多人都想参与一两个项目玩一玩学习一下,但由于是纯英文的网站,可能又会止步于想法上没有动手实践.接下来我就介绍一下参与github上开源 ...

  6. Azure ARM (7) ARM Template - 使用Visual Studio编辑

    <Windows Azure Platform 系列文章目录> 之前介绍的ARM Template,都是使用文本编辑器来编辑JSON文件的. 文本讲介绍如何使用Visual Studio, ...

  7. Windows Azure Virtual Network (10) 使用Azure Access Control List(ACL)设置客户端访问权限

    <Windows Azure Platform 系列文章目录> 本文介绍的是国内由世纪互联运维的China Azure. 我们在创建完Windows Azure Virtual Machi ...

  8. 16个时髦的扁平化设计的 HTML5 & CSS3 网站模板

    创建网站最好办法之一是使用现成的网站模板或使用开源 CMS 应用程序.所以,今天这篇文章给大家带来的是16款基于 HTML5 & CSS3 的精美的扁平风格网站模板,大家可以借助这些优秀的网站 ...

  9. Make something people want

    <黑客与画家>开头首先介绍了书的作者格雷厄姆的其人其事,他的成长涉猎很多,大学学哲学,研究生学计算机,博士时对绘画感兴趣,后来做了两年画家,但是入不敷出,后来他和朋友开始合伙开发一个搭建网 ...

  10. Windows 8 应用商店无法连接到网络的终极完美解决方案

    当你看到以下几个步骤的时候,你可能会不以为然,因为你已经试过了,还是没成功,依然提示"你的电脑没有连接到Internet或者现在无法使用Windows应用商店,要使用Windows应用商店, ...