JavaScript中的闭包

闭包的特点与形式

       闭包,作为一种特殊的结构,有其自身的特点和各种形式。

闭包的内在:自治的领域

       闭包的是指闭包的内部环境对外部不可见,也就是说闭包具有控制外部域的能力但是又能防止外部域对闭包的反向控制。换句话说,闭包的领域是对外封闭的。

       闭包的这一个特点不用过多解释,因为JavaScript闭包是通过function实现的,所以它天然具有基本的函数特征,在闭包内声明的变量,闭包外的任何环境中都无法访问的,除非闭包向外部环境提供了访问它们的接口。例如:

JavaScript之家欢迎你: http://www.jrose.cn/

 

      闭包的封闭性

<html>

<head>

       <title>Example闭包的封闭性</title>

</head>

<body>

<script>

<!--

       function dwn(s)

       {

              document.write(s + "<br/>");

       }

    //我们说匿名函数调用产生一个瞬时的闭包

//因此当调用结束后,私有变量无法访问,并且如果没有外部引用存在

JavaScript之家欢迎你: http://www.jrose.cn/

 

//内部对象就会被销毁

//而如果返回了函数,或者被全局引用,则闭包被保留了下来

//闭包中的内容被有选择地开放出来

       (function(){

              //封闭的私有域

              var innerX = 10, innerY = 20;

              //开放的公共域

              outerObj = {x : innerX, y : innerY} ;

       })();

      

       try{

              dwn(innerX); //内部数据无法访问

       }

       catch(ex){

              dwn("内部数据无法访问");

       }

       dwn(outerObj.x); //通过外部接口访问

-->

</script>

</body>

</html>

 

JavaScript之家欢迎你: http://www.jrose.cn/

 

访问外部环境

       我们说,闭包可以访问外部环境,前面我们已经见过闭包读外部环境的例子,事实上闭包不但可以读外部环境,还可以写外部环境。

 严格来说,外部环境既包括闭包外部的语法域也包括闭包外部的执行域。但是闭包对语法域环境的访问和普通函数一致,因此我们这里主要强调的是闭包对执行域环境的访问。

       下面是一个用闭包写外部环境的例子:

    闭包改变外部环境

<html>

<head>

       <title>Example闭包改变外部环境</title>

</head>

<body>

<script>

<!—

//定义一个计数器生成函数,生成某种类型的计数器

function counter(iden, addi)

{

       //闭包外部,函数counter“内部的参数iden的值在闭包被调用的时候会被改变

       return function(){

              //改变iden的值

              iden = iden+addi;

              return iden;

       }

}

//产程一个从0开始计数,每次计数值加1的计数器

var c1 = counter(0, 1); 

//产生一个从10开始计数,每次计数值减1计数器

var c2 = counter(10, -1);

for(var i = 0; i < 10; i++){

       //循环计数

       c1();

}

for(var i = 0; i < 10; i++){

       //循环计数

       c2();

}

-->

</script>

</body>

</html>

JavaScript之家欢迎你: http://www.jrose.cn/

 

       我们说c1c2通过调用counter构造了两个不同的计数器它们的初值分别是010,步长分别是1-1,在调用闭包时,我们用步长改变计数器值iden,使得计数器的值按照给定的步长递增。

 上面的例子用面向对象的思想也能够实现,但是用闭包从形式上要比用对象简洁一些,后面我们会看到,实际上我们在上面的例子中用了另外一种和面向对象等同的抽象思想,即函数式(functional)思想。

       有趣的是,外部环境的读写和闭包出现在函数体内的顺序没有关系,例如:

       function createClosure(){

              var x = 10;

return function()

              {

                     return x;

              }

}

       function createClosure(){

function a()

              {

                     return x;

              }

var x = 10;

return a;

}

的结果是一样的。

闭包和面向对象

       我们说,JavaScript的对象中的私有属性其实就是环境中的非持久型变量,而在构造函数内用this.foo = function(){…}形式定义的方法其实也是闭包的一种创建形式,只是它提供的是一种开放了外部接口的闭包:

  闭包和面向对象

<html>

<head>

       <title>Example 闭包和面向对象</title>

</head>

<body>

<script>

<!--

       function dwn(s)

       {

              document.write(s + "<br/>");

       }

       //定义一个Foo类型

       function Foo(a)

       {

              function _pC()  //私有的函数

              {

                     return a;

              }

//公有的函数,通过它产生的闭包可以访问对象内部的私有方法_pC()

              this.bar = function(){           

                     dwn("foo" + _pC() + "!");

              }

       }

       var obj = new Foo("bar");

       obj.bar(); //显示Foo bar!

-->

</script>

</body>

</html>

其他形式的闭包

       JavaScript的闭包不仅仅只有以上几种简单的形式,它还有其他更加诡异的形式,例如:

闭包的其他形式

<html>

<head>

       <title>Example 闭包的其他形式</title>

</head>

<body>

<script>

<!—

//测试函数,异步计数

function test()

{

    for (var i = 0; i < 5; i++)

    {

              //如果没有这个闭包,不能正确得到0,1,2,3,4的结果

              //因为setTimeout是在循环结束后才被异步调用的

        (function(j){

            setTimeout(function(){alert(j)}, 100);

        })(i);

    }

}

test();

-->

</script>

</body>

</html>

JavaScript之家欢迎你: http://www.jrose.cn/

 

这个例子我们曾经见到过,function(j){setTimeout(function(){alert(j)}, 100);}是一个闭包,它访问test()的调用环境,而function(){alert(j)}也是一个闭包,它又访问由外部闭包提供的环境。这样的闭包使用法经常被用在异步的环境中,用来将特定的引用绑定给闭包。例如,下面的用法通过闭包环境绑定修正了事件注册时的“this”指针:

button1.onclick =

(function(owner){return function(){button1_click.apply(owner,arguments)}})(button1);

JavaScript之家欢迎你: http://www.jrose.cn/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值