一. 匿名函数

1. 函数的定义,可分为三种

1) 函数声明方式

function double(x) {

    return 2*x;

}

2)Function构造函数,把参数列表和函数体都作为字符串,不方便,不建议使用

var double = new Function('x', 'return 2*x;');

3)函数表达式方式

var double = function(x) {

    return 2*x;

}

该形式中,等号右边是一个匿名函数,创建函数完毕后,将该函数赋给了变量double。

2. 匿名函数

1)第一种方式

var double= function(x) {

    return 2*x;

}

等号右边是一个匿名函数。注意匿名函数不能直接独立的房子代码中,如下代码

functino(x) {

    return 2*x;

}                  //SyntaxError: Unexpected token (

2)第二种方式

(function(x,y) {

    console.log(x+y);

})(2,3);

创建一个匿名函数(在第一个括号内),第二个括号用于调用该匿名函数并传入参数。

二. 闭包(Closure)

闭包的含义:外层函数包含内层函数,内层函数可以访问外层函数的所有变量,即使外层函数执行完毕。(JavaScript作用域链)

题外话:上述对于闭包的解释与《JavaScript 闭包系列一》中不完全吻合。 上述解释,闭包成立只需满足:函数inner嵌套在函数outer内部。另一些文章对于闭包的解释,闭包成立需要两个条件:1)函数inner嵌套在函数outer内部;2)函数outer返回函数inner。对此,我已经凌乱了,各路大侠谁能够给个定论

Example 1:

函数outer是瞬间执行的(约0.00001毫秒),在函数outer体内创建了一个变量str,在outer执行完毕后,str变量未被释放,这是由于setTimeout内的匿名函数存在对变量str的引用。等到2秒后,匿名函数执行完毕,str才被释放。

function outer() {

    var str = "closure";

    setTimeout(function() {

        console.log(str);

    }, 2000);

}

outer();  //closure

Example 2:此例是否为闭包呢?

function outer() {

    var i = 22;

    (function inner() {

        console.log(i);

    })();

}

outer();  //

Example 3:简化代码

function forTimeout(x, y) {

    console.log(x + y);

}

function delay(x, y, time) {

    setTimeout('forTimeout(' + x + ',' + y + ')', time);

}

//简化后

function delay(x, y, time) {

    setTimeout(

        function() {

            forTimeout(x,y);

        }

    ,time);

}

delay(3, 4, 2000); //

三. 匿名函数与闭包

匿名函数的最大用途是创建闭包,它也可用来构建命名空间,减少全局变量的使用。

Example1:

匿名函数中的addEvent和removeEvent为局部变量,但是可以通过全局变量oEvent使用它,大大减少了全局变量的使用,增强了网页的安全性。

var oEvent = {};

(function() {

    var addEvent = function() {};

    function removeEvent(){}

    oEvent.addEvent = addEvent;

    oEvent.removeEvent = removeEvent;

})();

Example2:

创建一个变量sun_mile_rain,并通过直接调用匿名函数初始化为5,这种小技巧有时十分有用。

var sun_mile_rain = (function(x , y){

    return x + y;

})(2 , 3);

console.log(sun_mile_rain);  //

//也可使用如下的方式,第一个括号只是帮助我们阅读,但是不推荐下面这种书写格式

var sun_mile_rain = function(x , y){

    return x + y;

}(2 , 3);

Example3:

代码中,变量one定义在函数内部,是一个局部变量,因此外部是不可以访问的。但inner函数可以访问变量one,又将全局变量outer引用了inner,因此执行outer()能访问到one的值。

var outer = null;

(function() {

    var one = 1;

    function inner() {

        one += 1;

        console.log(one);

    }

    outer = inner;

})();

outer();  //

outer();  //

outer();  //

换一种形式:函数fn执行,返回inner,将fn的执行结果赋给全局变量outer。执行outer也能访问到one的值。因此可得知闭包的形式可以有多种。

function fn() {

    var one = 1;

    function inner() {

        one += 1;

        console.log(one);

    }

    return inner;

}

var outer = fn();

outer();  //

outer();  //

outer();  //

四. 闭包与变量

闭包允许内层函数引用父函数中的变量,但该变量是最终值

鼠标移过每一个li元素时,控制台输出的值都是3,而不是我们期望的元素下标。当mouseover事件调用监听函数时,首先在匿名函数内部查找i是否定义,结果没找到,因此向上查找,在全局环境中找到i,并且i的值是3(循环后的值)。因此每次输出的都是3。

/*
<ul>
    <li>one</li>
    <li>two</li>
    <li>three</li>
</ul>
*/
var lists = document.getElementsByTagName("li");
for(var i=0; i<lists.length; i++) {
    lists[i].onmouseover = function() {
        console.log(i);
    }
}

注意:此处的闭包,并不是函数嵌套函数的形式,而是匿名函数包含在全局环境中的形式。

针对上述代码,有三种方法改进,使得鼠标移动到li元素上时,控制台输出对应的下标值。

1)立即执行的匿名函数

var lists = document.getElementsByTagName("li");
for (var i = 0; i < lists.length; i++) {
    (function(index) {
        lists[i].onmouseover = function() {
            console.log(index);
        };
    })(i);
}

2)在DOM元素上绑定$$index属性记录下标

var lists = document.getElementsByTagName("li");
for (var i = 0; i < lists.length; i++) {
    lists[i].$$index = i;
    lists[i].onmouseover = function() {
        console.log(this.$$index);
    };
}

3)

var lists = document.getElementsByTagName("li");
for (var i = 0; i < lists.length; i++) {
    eventListener(lists[i],i);
}
function eventListener(list,index) {
    list.onmouseover = function() {
        console.log(index);
    }
}

时间:2014-10-23

地点:合肥

引用:http://www.cnblogs.com/rainman/archive/2009/05/04/1448899.html

JavaScript 闭包系列二(匿名函数及函数的闭包)的更多相关文章

  1. Javascript数组系列二之迭代方法1

    我们在<Javascript数组系列一之栈与队列 >中介绍了一些数组的用法.比如:数组如何表现的和「栈」一样,用什么方法表现的和「队列」一样等等一些方法,因为 Javascript 中的数 ...

  2. Javascript基础系列之(七)函数(定义和调运函数)

    函数是一个可以随时运行的语句,简单说,函数是完成某个功能的一组语句,它接受0或者多个参数. 函数的基本语法如下 function functionName([arg0,arg1,......argN] ...

  3. Javascript基础系列之(七)函数(argument访问函数参数)

    argument是javascript中函数的一个特殊参数,例如下文,利用argument访问函数参数,判断函数是否执行 <script type="text/javascript&q ...

  4. Javascript基础系列之(七)函数(对象和属性)

    包含在对象里的数据可以通过两种方式来访问 既属性的对象(property)和方法(method) 属性是隶属于某个特定对象的变量,方法则是某个特定对象才能调运的函数. 对象是由一些彼此相关的属性和方法 ...

  5. Javascript设计模式系列二

    创建对象的基本模式,一.门户大开型,二.采用下划线来表示属性和方法的私用性,三.使用闭包来创建私用的成员. 一.门户大开型.只能提供公用成员.所有属性和方法都公开的.可访问的.这些共用属性都要使用th ...

  6. javascript设计模式系列二-封装

    JavaScript封装: var Book = function (id, name, price) { this.id = id, this.name = name, this.price = p ...

  7. js匿名自执行函数中闭包的高级使用(---------------------------******-----------------------------)

    先看看最常见的一个问题: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...

  8. Javascript数组系列三之迭代方法2

    今天我们来继续 Javascript 数组系列的文章,上文 <Javascript数组系列二之迭代方法1> 我们说到一些数组的迭代方法,我们在开发项目实战的过程中熟练的使用可以大大提高我们 ...

  9. Javascript数组系列五之增删改和强大的 splice()

    今天是我们介绍数组系列文章的第五篇,也是我们数组系列的最后一篇文章,只是数据系列的结束,所以大家不用担心,我们会持续的更新干货文章. 生命不息,更新不止! 今天我们就不那么多废话了,直接干货开始. 我 ...

随机推荐

  1. less文件编译成微信小程序wxss文件

    2016年9月21日,微信小程序正式开启内测.在微信生态下,触手可及.用完即走的微信小程序引起广泛关注,刷爆朋友圈子.在这样的火爆氛围中,作为一个前端开发者的我,也悄悄地去尝鲜.在做demo小示例的过 ...

  2. Stl源码剖析读书笔记之Alloc细节

    阅读基础: Foo *pf = new Foo; 执行了两个步骤: 1)::operator new 向系统申请内存. 2) 调用Foo::Foo()构造函数构造实例.  ==> 申请内存,构造 ...

  3. .proto 文件转js 文件方法【nodejs】

    npm install protobufjs -g pbjs proto\IM.Other.proto -t js>proto\IM.Other.js

  4. App开发(Android与php接口)之:短信验证码

    最近和同学们一起开发一个自主项目,要用到短信验证码,在网上搜索了很久,看到一个推荐贴,提到了很多不错的短信服务商.经过测试,帖子中提到的服务商他们的短信到达率和到达速度也都不错.最后,由于经费问题,我 ...

  5. 简单的canvas时钟

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. iOS - WXPay 微信支付

    1.微信支付申请 微信支付官方集成指引 微信支付官方集成指导视频 微信 APP 支付开发者文档 微信公众平台 微信开放平台 微信商户平台 1.1 微信 APP 支付申请步骤 APP 支付:APP 支付 ...

  7. Load Runner录制C/S客户端

    1.    打开应用程序 2.    点击如下菜单 弹出窗口如下 3.    点击New,弹出窗口如下,选择Web(HTTP/HTML) 4.    点击Create,弹出窗口 5.    点击OK, ...

  8. 用原生js获取class

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  9. 给libpcap增加一个新的捕包方法

    libpcap是一个网络数据包捕获函数库,功能非常强大,提供了系统独立的用户级别网络数据包捕获接口,Libpcap可以在绝大多数类unix 平台下工作.大多数网络监控软件都以它为基础,著名的tcpdu ...

  10. postgres 类型转换 cast 转

    转自: http://blog.csdn.net/yufenghyc/article/details/45869509 --1 例子postgres=# select 1/4; ?column? -- ...