`
mrzhanghuzi
  • 浏览: 25002 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

面向对象的 Javascript 语言特性:闭包(转)

阅读更多
转自(http://www.cnblogs.com/zitiger/archive/2007/06/08/776777.html)
闭包

  闭包意味着内层的函数可以引用存在于包绕它的函数的变量,即使外层的函数的执行已经终止。这一特殊的论题可能是非常强大又非常复杂的。我强烈推荐你们参考本节后面将提及的站点,因为它有一些关于闭包这一话题的精彩的信息。
  我们先来看程序2-13所示的闭包的两个简单例子。
  
  程序2-13. 闭包改善的代码清晰性的两例


//得到id为"main"的元素
var obj = document.getElementById("main");

//改变它的边框样式
obj.style.border = "1px solid red";

//初始化一个1秒钟以后被调用的回调函数
setTimeout(function(){
    //此函数将隐藏该元素
    obj.style.display = 'none';
}, 1000);

//用来延迟显示消息的通用函数
function delayedAlert( msg, time ) {
    //初始化一个被封套的函数
    setTimeout(function(){
        //此函数使用了来自封套它的函数的变量msg
        alert( msg );
    }, time );
}

//调用函数delayedAlert,带两个参数
delayedAlert( "Welcome!", 2000 );


  第一个对setTimeout的函数调用,展示了一个的JavaScript新手遇到问题的通俗的例子。在JavaScript新手的程序里像这样的代码时常可以看到:


setTimeout("otherFunction()", 1000);

//或者甚至
setTimeout("otherFunction(" + num + "," + num2 + ")", 1000);


  使用闭包的概念,完全可能的把这种混乱的代码清理掉。第一个例子很简单;有一个回调函数在调用setTimeout函数以后1000微秒以后被调用,而它仍引用了变量obj(定义在全局范围,指向id为"main"的元素)。定义的第二个函数,delayedAlert,展示了一种解决出现的setTimeout混乱的方案,以及函数作用域内可以有闭包的能力。
  你们应该可以发现,当在代码中使用这种简单的闭包时,你所写的东西的清晰性将会提高,免于陷入语法的迷雾之中。
  我们来看一个闭包可能带来的有有趣的副作用。在某些函数化的编程语言里,有一个叫做currying的概念。本质上讲,currying是就是为函数的一些参数预填入值,创建一个更简单的新函数的方法。代码2-14里有一个简单的currying的例子,创建了向另一个函数预填一个参数而得的新函数。

  代码2-14. 使用闭包的函数currying


//生成做加法的新函数的函数
function addGenerator( num ) {
    //返回一个简单函数用来计算两个数的加法,
    //其中第一个数字从生成器中借用
    return function( toAdd ) {
        return num + toAdd
    };
}

//addFive现在是接受一个参数的函数,
//此函数将给参数加5,返回结果数字
var addFive = addGenerator( 5 );

//这里我们可以看到,当传给它参数4的时候
//函数addFive的结果为9
alert( addFive( 4 ) == 9 );


  闭包还能解决另一个常见的JavaScript编码方面的问题。JavaScript新手趋向于在全局作用域里放置许多变量。这一般被认为是不好的习惯,因为那些变量可能悄悄地影响其它的库,导致令人迷惑的问题的产生。使用一个自执行的、匿名的函数,你可以从根本上隐藏所有的通常的全局变量,使它们对其它代码不可见,如程序2-15所示。
  
  代码2-15. 使用匿名函数从全局作用域隐藏变量的例子


//创建一个用作包装的匿名函数
(function(){
    //这个变量通常情况下应该是全局的
    var msg = "Thanks for visiting!";

    //为全局对象绑定新的函数
    window.onunload = function(){
        //使用了“隐藏”的变量
        alert( msg );
    };

//关闭匿名函数并执行之
})();


  最后,让我们来看使用闭包时出现的一个问题。闭包允许你引用存在于父级函数中的变量。然而,它并不是提供该变量创建时的值;它提供的是父级函数中该变量最后的值。你会看到这个问题最通常是在一个for循环中。有一个变量被用作迭代器(比如i),在for内部新的函数被创建,并使用了闭包来引用该迭代器。问题是,当新的闭包函数被调用时,它们将会引用该iterator最后的值(比如,一个数组的最后位置),而不是你所期望的那个。程序2-16的例子说明,使用匿名函数激发作用域,在其中创建一个合乎期望的闭包是可能的。

  程序2-16. 使用匿名函数激发一个创建多个闭包函数所需的作用域的例子


//id为"main"的一个元素
var obj = document.getElementById("main");

//用来绑定的items数组
var items = [ "click", "keypress" ];

//遍历items中的每一项
for ( var i = 0; i < items.length; i++ ) {
    //用自执行的匿名函数来激发作用域
    (function(){
        //在些作用域内存储值
        var item = items[i];
        //为obj元素绑定函数
        obj[ "on" + item ] = function() {
            //item引用一个父级的变量,
            //该变量在此for循环的上文中已被成功地scoped(?)
            alert( "Thanks for your " + item );
        };
    })();
}


  闭包的概念并非轻易可以掌握的;我着实花了大量的时间和精力才彻底弄清闭包有多么强大。幸运的是,有一个精彩的资源解释了JavaScript中的闭包是怎么工作的:Jim Jey的"JavaScript闭包",网址是http://jibbering.com/faq/faq_notes/closures.html。

最后,我们将研究上下文的概念,这是许多JavaScript的面向对象特性赖以建立的基石。
分享到:
评论
1 楼 我不说话 2010-10-25  
把精通javascript上的完完整整的抄来了.

相关推荐

    JavaScript面向对象编程指南

    如何应用适当的编程模式,发挥JavaScript语言特有的优势;如何应用设计模式解决常见问题等。, 《JavaScript面向对象编程指南》着重介绍JavaScript在面向对象方面的特性,展示如何构建强健的、可维护的、功能强大的...

    JavaScript面向对象编程指南.pdf

    JavaScript作为一门浏览器语言的核心思想;面向对象编程的基础知识及其在... 《JavaScript面向对象编程指南》着重介绍JavaScript在面向对象方面的特性,展示如何构建强健的、可维护的、功能强大的应用程序及程序库

    javascript面向对象编程

    JavaScript作为一门浏览器语言的核心思想;...如何实现JavaScript中缺失的面向对象特性,如对象的私有成员与私有方法;如何应用适当的编程模式,发挥JavaScript语言特有的优势;如何应用设计模式解决常见问题等。

    JavaScript面向对象编程指南 英文版

    如何应用适当的编程模式,发挥JavaScript语言特有的优势;如何应用设计模式解决常见问题等。 《JavaScript面向对象编程指南》着重介绍JavaScript在面向对象方面的特性,展示如何构建强健的、可维护的、功能强大的...

    JavaScript面向对象编程指南 有书签

    如何应用适当的编程模式,发挥JavaScript语言特有的优势;如何应用设计模式解决常见问题等。 《JavaScript面向对象编程指南》着重介绍JavaScript在面向对象方面的特性,展示如何构建强健的、可维护的、功能强大的...

    Javascript面向对象编程

    Javascript的重要性 使用率 1、在web应用中,涉及到前端界面编程基本上都要用到javascript语言; 2、Web2.0及Ajax推动了javascript语言。...他具有面向对象语言所特有的各种特性,比如封装、继承及多态等。但对于

    全面理解面向对象的 JavaScript(来自ibm)

    当今 JavaScript 大行其道,各种应用...要掌握好 JavaScript,首先一点是必须摒弃一些其他高级语言如 Java、C# 等类式面向对象思维的干扰,全面地从函数式语言的角度理解 JavaScript 原型式面向对象的特点。把握好这一

    JavaScript核心概念及实践 高清PDF扫描版 (邱俊涛).pdf

     1.2 JavaScript语言特性   1.3 JavaScript应用范围  第2章 基本概念   2.1 数据类型   2.2 变量   2.3 运算符  第3章 对象   3.1 JavaScript对象   3.2 使用对象   3.3 对象字面量   ...

    JavaScript函数式编程

    JavaScript 是近年来非常受瞩目的一门编程语言,它既支持面向对象编程,也支持函数式编程。本书专门介绍JavaScript函数式编程的特性。 全书共9章,分别介绍了JavaScript函数式编程、一等函数与Applicative编程、...

    全面理解面向对象的JavaScript

    要掌握好JavaScript,首先一点是必须摒弃一些其他高级语言如Java、C#等类式面向对象思维的干扰,全面地从函数式语言的角度理解...这都是对原生JavaScript语言特性理解不够的表现。要掌握好JavaScript,首先一点是必须摒

    javascript面向对象三大特征之封装实例详解

    在JavaScript语言中没有提供专门的信息封装关键字,不过可以使用闭包来创建,只允许从对象内部访问的方法和属性。另外,接口也是数据封装的一种工具,接口提供了外界访问方法的约定。在应用开发中,所有类都应定义...

    javascript使用闭包模拟对象的私有属性和方法

    最近因为做了一个项目,其中涉及到了js私有方法,这个概念在其语言里面是很常见的,很多语言都有private这个关键字,只要在一个类的前面加上private就表示申明了一个私有方法,但是javascript在面向对象的方面没有...

Global site tag (gtag.js) - Google Analytics