对JavaScript闭包的理解
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。
在开始了解闭包前我们必须要先理解JavaScript的变量作用域。
一、变量的作用域无非就是两种:全局变量和局部变量。
用两个小例子回顾变量作用域:
函数内部可以直接读取全局变量:
var a = 123; function con(){ alert(a); } con(); //
函数外部无法读取函数内的局部变量。
function con(){ var a = 123;
} alert(a); //error
在这里有个地方需要注意,函数内部声明变量的时候,一定要用var命令。如果不用的话,你实际上声明了一个全局变量!
function con(){ a = 123; } con(); alert(a); //error
二、那么问题来了,我们怎么从外部读取局部变量?
在正常的情况下是不可能办到的,只有变通方法才能实现!
下面有个简单的闭包:
function con1(){ var a = 123; function con2(){
alert(a);
} return con2;
} var result = con1(); result(); //
以上的con2函数,就是闭包。
闭包是指有权访问另一个函数作用域中的变量的函数。而创建闭包的常见方式,就是在一个函数内部创建另一个函数。
阮前辈的说法是:闭包就是能够读取其他函数内部变量的函数。
其实道理都一样,指明的也是同一个观点,只是说辞不一样而已。
三、闭包的用途
闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); //
nAdd();
result(); //
在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。
为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。
这段代码中另一个值得注意的地方,就是"nAdd=function(){n+=1}"这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。
四:使用闭包的注意点
1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
五:两个例子强化对闭包的理解
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()()); //"The window"
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()()); //"My Object"
对JavaScript闭包的理解的更多相关文章
- javascript闭包的理解
闭包是Javascript的一个难点,但也是一个很重要的知识点. 1.首先我们要知道变量作用域链 变量的作用域分两种:全局变量和局部变量.没有定义到任何函数中的变量为全局变量,在函数中定义的变量为局部 ...
- 我对 javascript 闭包的理解
学js的学到闭包,但是理解不深. 后来看了一下这篇文章: 地址:http://leepiao.blog.163.com/blog/static/4850313020112835355917/ 内容如下 ...
- javascript 闭包的理解(一)
过很多谈如何理解闭包的方法,但大多数文章,都是照抄或者解释<Javascript高级程序设计(第三版)>对于闭包的讲解,甚至例程都不约而同的引用高程三181页‘闭包与变量’一节的那个“返回 ...
- 关于Javascript 闭包的理解
一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话 ...
- 关于Javascript闭包的理解
以下内容属个人理解,如有看不明白或漏洞之处,纯属水平不佳,还望见谅. 关于闭包,高程里的定义是:指有权访问另一个函数作用域中的变量的函数.创建闭包最常见的方法就是在一个函数的内部再创建一个函数. 这里 ...
- javascript闭包的理解和实例
所谓闭包,值得是词法表示包括不必要计算的变量的函数,也就是说,该函数可以使用函数外定义的变量. 顺便提示一下: 词法作用域:变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通 ...
- Javascript闭包简单理解
提到闭包,想必大家都早有耳闻,下面说下我的简单理解.平时写代码.第三方框架和组件都或多或少用到了闭包.所以,了解闭包是非常必要的.呵呵... 一.什么是闭包简而言之,就是能够读取其他函数内部变量的函数 ...
- javascript 闭包的理解(二)
// 定义一个User构造函数 function User(properties){ //遍历对象属性,确保它作用域正确 for(var i in properties){ (function(whi ...
- javascript 闭包的理解
1 需要明白概念: 执行环境 变量对象,活动对象 作用域,作用域链 闭包 垃圾处理机制 闭包陷阱
随机推荐
- jquery页面水印插件,支持多行水印、行错开
最近工作需求,需要在页面上加水印,但发现网上示例无法满足我的需求,所以还是自己动手写. 有几个特别需求: 1.可以写多行水印,并且中心对齐. 2.每行水印错开. PS:我找到的例子都是单行水印,所以用 ...
- 快速上手 Kotlin 的 11 招
本文转载自 Kotlin 公众号(KotlinX) 作者:bennyhuo 最近经常会收到一些 "用 Kotlin 怎么写" 的问题,作为有经验的程序员,我们已经掌握了一门或者多门 ...
- java基础之集合篇
(一) 集合类位于JDK中java.util包中. 常用的集合类型分布在java.util.Collection和java.util.Map接口中. java.util.Collection=> ...
- 微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计(微服务架构实施原理)
版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 基于微服务架构和Docker容器技术的PaaS云平台建设目标是给我们的开发人员提供一套服务快速开发.部署.运维管理.持续开发持续集成的流程 ...
- 盒子模型,定位技术,负边距,html5 新增标签
盒子模型 /*[margin 外边距] margin属性最多四个 1.只写一个值,四个方向的margin均为这个值 2.写两个值:上,右两个方向,下默认=上,右 默认=左 3.写三个值:上.右.下三个 ...
- C#继承的执行顺序
自己对多态中构造函数.函数重载执行顺序和过程一直有些不理解,经过测试,对其中的运行顺序有了一定的了解,希望对初学者有些帮助. eg1: public class A { public A() { Co ...
- jquery里的attr()方法和prop()方法的区别
在jq的高版本里出现了prop()方法,那么attr()和prop()的区别在哪呢?这两者分别在什么情况用呢? 对于HTML元素本身就带有的固有属性,在处理时,使用prop方法. 对于HTML元素我们 ...
- windows下python连接oracle数据库
1.首先安装cx_Oracle包2.解压instantclient-basic-windows.x64-11.2.0.4.0.zip到c:\oracle3.拷贝instantclient_11_2下所 ...
- EntityFramework.Extended.Update.Ambiguous column name
异常描述 c#代码 dbcontext.Table.Where(x => x.B > 0).Update( x => new Table() { A = x.B } ) 抛出异常: ...
- [LeetCode] Friend Circles 朋友圈
There are N students in a class. Some of them are friends, while some are not. Their friendship is t ...