js 闭包 理解
1.什么是闭包
定义:是指有权访问另一个函数作用域中的变量的函数
创建闭包:在一个函数内部创建另一个函数
基本特点 在返回的匿名函数中 可以调用外部函数的变量 如下例中所示 内部函数(匿名函数) 可以访问外部函数的变量num 形式如a[num] 原因是匿名函数作用域链中包括外部函数test1的作用域
闭包有权访问包含函数内部的所有变量 如下面的 外部函数定义变量d 在闭包中可以直接访问到d (var dd=d)
function test1(num){
var d;
return function(a,b){
var d1=a[num],d2=b[num];
var dd=d;
}
}
实例参考 此时点击产品1 到 产品4 结果都是5 点击匿名函数的作用域链中包括外部函数init的活动对象 都是引用的同一个变量i 都是5 。解决办法 返回的匿名函数 通过立即执行函数 把参数i传给匿名函数
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<title>闭包演示</title>
<style type="text/css">
p {background:gold;}
</style>
<script type="text/javascript">
function init() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
pAry[i].onclick = function() {
alert(i);
}
}
} </script>
</head>
<body onload="init();">
<p>产品 0</p>
<p>产品 1</p>
<p>产品 2</p>
<p>产品 3</p>
<p>产品 4</p>
</body>
</html>
弹出结果都是5截图

解决办法:立即执行匿名函数 参数i是循环i的值 传递给num形参 匿名函数里 在创建闭包 可以访问这个传递过来的值num
pAry[i].onclick = function(num){//......}(i)
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<title>闭包演示</title>
<style type="text/css">
p {background:gold;}
</style>
<script type="text/javascript">
/*修改后*/
function init() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
pAry[i].onclick = function(num) { return function(){
alert(num)
}
}(i)
}
} </script>
</head>
<body onload="init();">
<p>产品 0</p>
<p>产品 1</p>
<p>产品 2</p>
<p>产品 3</p>
<p>产品 4</p>
</body>
</html>
结果点击第一展示

还有这样写也是可以的
function a(){
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
(function(num){
pAry[num].onclick = function() {
alert(num);
}
})(i)
}
}
1.1 闭包的原理
-1) 闭包的作用域链 包括 闭包自身的作用域(一般返回匿名函数的作用域),外部函数的作用域(包含的外部函数),全局作用域
-2)通常,函数的作用域和所有变量都会在函数执行结束后被销毁
-3)函数返回一个闭包,这个函数的作用域会一直保存在内存中直到闭包不存在为止
使用闭包可以模仿块级作用域
-1)创建闭包并立即执行这个函数 不会再内存中留下该函数的引用
-2 )结果 函数内部的所有变量都会被立即销毁
2.什么是作用域链
执行环境:定义了变量或函数有权访问其他数据,决定它们各自的行为。
变量对象:每个执行环境都有一个与之关联的变量对象。
执行环境定义的所有变量和函数都保存在变量对象中。编写代码无法访问这个对象,解析器在处理数据时会在后台使用它。
-1)全局执行环境是最外围的一个执行环境
-2)web浏览器中,全局执行环境默认是window对象,因此所有全局变量和函数都是作为window对象的属性和方法创建的
-3)某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义都随之销毁 全局执行环境直到应用程序退出--例如关闭网页或浏览器时才会被销毁
-4)每个函数都有自己的执行环境
作用域链:当代码在一个执行环境中执行时,会创建变量对象 一个作用域链
作用域链用途:保证对执行环境有权访问的所有变量和函数的有序访问
标识符解析:沿着作用域链一级一级的向上搜索标识符的过程。
函数参数也被当做变量来看待,因此访问规则与执行环境中的其它变量相同。 例子:下面函数chageColor(num){} 在闭包里tempColor(a){}里可用a[num]访问
实例解析
<script type="text/javascript">
/*全局变量*/
var color = 'red' ; function changeColor(num){
var otherColor = 'blue',
another =color,
chage = changeColor(); function tempColor(a){
var temp = otherColor,
temp2 = color,
temp3 = changeColor();/*这里可以访问上层执行环境otherColor another chage 和全局color*/
var u =a[num]; } }
</script>
全局 window
|
|-------------color 全局变量
|------------changeColor()
|
|---------------otherColor(局部变量 还有两个就是调用的上层全局环境里的color变量和函数chageColor)
|---------------tempColor()
|-------------------h(变量h不能被上层执行环境调用 只能在tempColor()里调用 标识符向上搜索沿着作用域链 这个环境里可以调用外层环境和全局环境的变量)
参考:
http://www.cnblogs.com/yugege/p/6526215.html 闭包
js 闭包 理解的更多相关文章
- js闭包理解实例小结
Js闭包 闭包前要了解的知识 1. 函数作用域 (1).Js语言特殊之处在于函数内部可以直接读取全局变量 <script type="text/javascript"> ...
- js闭包理解
js闭包的作用是使函数外可以访问函数内部的变量,是通过 在函数内部 定义 访问函数内变量 的函数实现的,内部的一个函数产生一个闭包 function a() { var i=0; return fun ...
- JS闭包理解_摘
原文地址1:http://www.cnblogs.com/mzwr1982/archive/2012/05/20/2509295.html 闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实 ...
- js闭包理解案例-解决for循环为元素注册事件的问题
转发自http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html 一.变量的作用域 要理解闭包,首 ...
- js 闭包 理解 copy
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于Javascript初学者应该是很有用的. 一.变量的作用域 要理解 ...
- js闭包理解与使用场景
要理解闭包首先要知道什么是函数的作用域链 因为有函数的作用域链存在,所以函数无论在哪里调用,函数都可以使用函数外部作用域的变量. 当一个函数被调用时,会创建一个执行环境及相应的作用域链.然后使用arg ...
- js 闭包理解
闭包主要应用于两种情况: 1 函数作为返回值. 2 函数作为参数传递. 第一种举例: function fn(){ var max = 10; return function bar(){ if(x ...
- js闭包之初步理解( JavaScript closure)
闭包一直是js中一个比较难于理解的东西,而平时用途又非常多,因此不得不对闭包进行必要的理解,现在来说说我对js闭包的理解. 要理解闭包,肯定是要先了解js的一个重要特性, 回想一下,那就是函数作用域, ...
- (原创)JS闭包看代码理解
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...
随机推荐
- Linux 使用iostat分析IO性能
原文:http://www.cnblogs.com/bangerlee/articles/2547161.html 对于I/O-bond类型的进程,我们经常用iostat工具查看进程IO请求下发的数量 ...
- POJ 1325 Machine Schedule——S.B.S.
Machine Schedule Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 13731 Accepted: 5873 ...
- 三维网格补洞算法(Radial Basis Function)
在逆向工程中,由于设备或模型的原因,我们获取得到的三维模型数据往往并不完整,从而使得生成的网格模型存在孔洞,这对后续的模型分析会造成影响.下面介绍一种基于径向基函数(RBF:Radial Basis ...
- 对象比较器:Comparable和Comparator
在进行对象数组排序的过程中需要使用到比较器,比较器有两个:Comparable和Comparator ①.java.lang.Comparable:是在类定义是时候默认实现好的接口,里面提供有一个co ...
- JSP 错题
(选择一项) 8 A: B: C: D: 正确答案是 D 您回答的是 A 回答错误 试题分析:web容器处理JSP文件请求的三个阶段翻译阶段:这一个阶段,编写好的jsp文件首先被web容器中的 ...
- [No000076]用Eclipse编写python(配置PyDev插件)
下载,安装python解释器 地址:https://www.python.org/downloads/ 下载,安装java jdk 地址:http://www.oracle.com/technetwo ...
- 如何使用eclipse打开已有工程
在开始使用Eclipse的时候,会发现一个问题,那就是如何打开一个现有的Eclipse工程,开始在菜单中找了好久也没找到. 其实,Eclipse生成的结果不像VC,Jcreator那样可以直接打开,若 ...
- 用table做网页,设置了border为1px怎么还是觉得很粗?
设置边框重叠 border-collapse:collapse; /*边框重叠*/ 例: <table width="700" style="border-col ...
- [LeetCode] Wiggle Sort
Problem Description: Given an unsorted array nums, reorder it in-place such that nums[0] <= nums[ ...
- 怎么在Microsoft Project中冻结列
在用Project排项目计划的时候如果在Gantt图中列比较多,左右滚动的时候就会经想像如果能想Excel一样冻结某些列就方便多了,其实在Project中虽然没有冻结列的功能,但通过一些变通方法还是可 ...