第二话:javascript中闭包的理解
闭包是什么?
通过闭包,子函数得以访问父函数的上下文环境,即使父函数已经结束执行。
OK,我来简单叙述下,先上图。
都知道函数是javascript整个世界,对象是函数,方法是函数,并且js中实质性的面向对象相关也都是函数来实现和延伸,例如:“类”。
window:是指js中window对象,也是js最高一层,因为什么这么说,因为你所有创建的方法和属性其实都在window之内。window中的所有方法,在手动创建的方法中都可以调到。可以仔细想想alert,在任何地方都可以alert,其实alert就是window内部的一个方法。window.alert()。具体参看:JavaScript Window - 浏览器对象模型
回到图上:
那么我创建的每一个全局function其实都是window的方法,所以window把a()和b()包含;但d()和e()呢?他们是局部的。a()包含d(),b()包含e();由此推出下面代码:
function window(){ //虚构出来的,只为说明问题,因为window属于浏览器内置类,所以根本看不到 function a(){ var a = 1; function d(){ var d = 3; alert(a+d); //4 } } function b(){ var b = 1; function e(){ var e = 4; alert(b+e); } } }
其实闭包的概念已经包含在这个函数中,d()中可以访问a()中定义的a变量和window中声明的所有变量和函数,e()中可以访问b()中的b变量和window中声明的所有变量和函数。
完毕。
闭包中最常见的用途是声明事件处理器和匿名空间使用:
声明事件处理器
function a(){ var obj = document.getElementById("text"); obj.onclick = function(){ obj.innerHTML = " hello world!"}; }
绑定到onclick上的函数建立了一个闭包,所以它能访问obj变量。
function a(){ var obj = document.getElementById("text"); obj.onclick = clickHandler; } function clickHandler(){ function(){ obj.innerHTML = " hello world!"}; }
clickHandler并不能访问到obj,因为clickHandler定义在a()外部。
闭包引用可以避免this调用造成的恐慌。
function launcher(element,message){ function openWin(){ alert(message); } window.addEventListener("click",element,false); } launcher("document.getElementById("text")","hello world!");
匿名空间:
在js组件开发之中,如果涉及到无穷多的组件加载,那命名冲突不可避免。
例如:
//组件1 var abc = 5; function TabView(cfg){ this.a = cfg.a; this.b = cfg.b; } TabView.protype = { c:function(){ abc++;}; d:function(){abc--}; } //组件2 var abc = 100; function TreeView(cfg){ this.a = cfg.a; this.b = cfg.b; } TreeView.protype = { c:function(){ abc*=2;}; d:function(){abc/=2;}; }
如果一个项目同时需要加载这两个组件,那么就会出现命名冲突;因此我们需要来避免这种问题,通过采用匿名空间-----闭包的办法;
//组件1 (function (){ var abc = 5; function TabView(cfg){ this.a = cfg.a; this.b = cfg.b; } TabView.protype = { c:function(){ abc++;}; d:function(){abc--}; } window.TabView = TabView; //将TabView类公开(作用域在window下)。除该类以外所有匿名空间内部定义,都对外界不形成干扰; })(); //组件2 (function (){ var abc = 100; function TreeView(cfg){ this.a = cfg.a; this.b = cfg.b; } TreeView.protype = { c:function(){ abc*=2;}; d:function(){abc/=2;}; } window.TreeView = TreeView; //将TabView类公开(作用域在window下)。除该类以外所有匿名空间内部定义,都对外界不形成干扰; })() 外部调用的时候只需: var tabView = new TabView(); var treeView = new TreeView();
ok,细细回味,闭包会带来很多方便……
最新文章
- Bubble Cup 8 finals H. Bots (575H)
- Windows下C编程获取软件安装列表信息
- 基于STM32Cube的DAC数模转化
- iOS7上在xib中使用UITableViewController设置背景色bug
- 数据包判断是否丢包 ping+tracert+mtr
- smarty安装及例子
- android开发,assets下面的资源文件不会变化/改动
- MVC三和,你能辨别它?
- 【转】CentOS 使用yum命令安装出现错误提示”could not retrieve mirrorlist http://mirrorlist.centos.org ***”
- JavaScript学习之获取URL参数
- js 玩一玩
- 07_jquery入门第一天
- Windows Server 2008 R2 下载地址
- (小技巧)Sql server查看sql语句的执行时间(转)
- 源码编译安装libtool工具
- p3396 哈希冲突(暴力)
- Python示例
- RabbitMQ学习之延时队列
- 阿里八八Alpha阶段Scrum(5/12)
- Mysql表创建外键报错