详谈JavaScript 匿名函数及闭包
1、匿名函数
函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途。匿名函数:就是没有函数名的函数。
1.1 函数的定义,首先简单介绍一下函数的定义,大致可分为三种方式
第一种:这也是最常规的一种
function double(x){
return 2 * x;
}
第二种:这种方法使用了Function构造函数,把参数列表和函数体都作为字符串,很不方便,不建议使用。
var double = new Function('x', 'return 2 * x;');
第三种:
var double = function(x) { return 2* x; }
注意“=”右边的函数就是一个匿名函数,创造完毕函数后,又将该函数赋给了变量square。
1.2 匿名函数的创建
第一种方式:就是上面所讲的定义square函数,这也是最常用的方式之一。
第二种方式:
(function(x, y){
alert(x + y);
})(2, 3);
这里创建了一个匿名函数(在第一个括号内),第二个括号用于调用该匿名函数,并传入参数。
2、闭包
闭包的英文单词是closure,这是JavaScript中非常重要的一部分知识,因为使用闭包可以大大减少我们的代码量,使我们的代码看上去更加清晰等等,总之功能十分强大。
闭包的含义:闭包说白了就是函数的嵌套,内层的函数可以使用外层函数的所有变量,即使外层函数已经执行完毕(这点涉及JavaScript作用域链)。
示例一
function checkClosure(){
var str = 'rain-man';
setTimeout(
function(){ alert(str); } //这是一个匿名函数
, 2000);
}
checkClosure();
这个例子看上去十分的简单,仔细分析下它的执行过程还是有许多知识点的:checkClosure函数的执行是瞬间的(也许用时只是0.00001毫秒),在checkClosure的函数体内创建了一个变量str,在checkClosure执行完毕之后str并没有被释放,这是因为setTimeout内的匿名函数存在这对str的引用。待到2秒后函数体内的匿名函数被执行完毕,str才被释放。
示例二,优化代码
function forTimeout(x, y){
alert(x + y);
}
function delay(x , y , time){
setTimeout('forTimeout(' + x + ',' + y + ')' , time);
}
/**
* 上面的delay函数十分难以阅读,也不容易编写,但如果使用闭包就可以让代码更加清晰
* function delay(x , y , time){
* setTimeout(
* function(){
* forTimeout(x , y)
* }
* , time);
* }
*/
3、举例
匿名函数最大的用途是创建闭包(这是JavaScript语言的特性之一),并且还可以构建命名空间,以减少全局变量的使用。
示例三:
var oEvent = {};
(function(){
var addEvent = function(){ /*代码的实现省略了*/ };
function removeEvent(){}
oEvent.addEvent = addEvent;
oEvent.removeEvent = removeEvent;
})();
在这段代码中函数addEvent和removeEvent都是局部变量,但我们可以通过全局变量oEvent使用它,这就大大减少了全局变量的使用,增强了网页的安全性。 我们要想使用此段代码:oEvent.addEvent(document.getElementById('box') , 'click' , function(){});
示例四:
var rainman = (function(x , y){
return x + y;
})(2 , 3);
/**
* 也可以写成下面的形式,因为第一个括号只是帮助我们阅读,但是不推荐使用下面这种书写格式。
* var rainman = function(x , y){
* return x + y;
* }(2 , 3);
*/
在这里我们创建了一个变量rainman,并通过直接调用匿名函数初始化为5,这种小技巧有时十分实用。
示例五:
var outer = null;
(function(){
var one = 1;
function inner (){
one += 1;
alert(one);
}
outer = inner;
})();
outer(); //2
outer(); //3
outer(); //4
这段代码中的变量one是一个局部变量(因为它被定义在一个函数之内),因此外部是不可以访问的。但是这里我们创建了inner函数,inner函数是可以访问变量one的;又将全局变量outer引用了inner,所以三次调用outer会弹出递增的结果。
4、注意
4.1 闭包允许内层函数引用父函数中的变量,但是该变量是最终值
示例六:
/**
* <body>
* <ul>
* <li>one</li>
* <li>two</li>
* <li>three</li>
* <li>one</li>
* </ul>
*/
var lists = document.getElementsByTagName('li');
for(var i = 0 , len = lists.length ; i < len ; i++){
lists[ i ].onmouseover = function(){
alert(i);
};
}
你会发现当鼠标移过每一个<li&rt;元素时,总是弹出4,而不是我们期待的元素下标。这是为什么呢?注意事项里已经讲了(最终值)。显然这种解释过于简单,当mouseover事件调用监听函数时,首先在匿名函数( function(){ alert(i); })内部查找是否定义了 i,结果是没有定义;因此它会向上查找,查找结果是已经定义了,并且i的值是4(循环后的i值);所以,最终每次弹出的都是4。
解决方法一:
var lists = document.getElementsByTagName('li');
for(var i = 0 , len = lists.length ; i < len ; i++){
(function(index){
lists[ index ].onmouseover = function(){
alert(index);
};
})(i);
}
解决方法二:
var lists = document.getElementsByTagName('li');
for(var i = 0, len = lists.length; i < len; i++){
lists[ i ].$$index = i; //通过在Dom元素上绑定$$index属性记录下标
lists[ i ].onmouseover = function(){
alert(this.$$index);
};
}
解决方法三:
function eventListener(list, index){
list.onmouseover = function(){
alert(index);
};
}
var lists = document.getElementsByTagName('li');
for(var i = 0 , len = lists.length ; i < len ; i++){
eventListener(lists[ i ] , i);
}
详谈JavaScript 匿名函数及闭包的更多相关文章
- 第一百一十节,JavaScript匿名函数和闭包
JavaScript匿名函数和闭包 学习要点: 1.匿名函数 2.闭包 匿名函数就是没有名字的函数,闭包是可访问一个函数作用域里变量的函数.声明:本节内容需要有面向对象和少量设计模式基础,否则无法听懂 ...
- [从jQuery看JavaScript]-匿名函数与闭包(Anonymous Function and Closure)【转】
(function(){ //这里忽略jQuery所有实现 })(); 半年前初次接触jQuery的时候,我也像其他人一样很兴奋地想看看源码是什么样的.然而,在看到源码的第一眼,我就迷糊了.为什么只有 ...
- 浅谈JavaScript匿名函数与闭包
一. 匿名函数 //普通函数定义: //单独的匿名函数是无法运行的.就算运行了,也无法调用,因为没有名称. 如: function(){ alert('123'); ...
- 深入理解javascript 匿名函数和闭包
代码如下: (function(){ //这里忽略jQuery所有实现 })(); (function(){ //这里忽略jQuery所有实现 })(); 半年前初次接触jQuery的时候,我也像其 ...
- Javascript 匿名函数与闭包
请见如下一个闭包示例: color = "red"; var obj = { color: "blue", getColor: function () { fu ...
- [从jQuery看JavaScript]-匿名函数与闭包
jQuery片段: (function(){ //这里忽略jQuery所有实现 })(); 半年前初次接触jQuery的时候,我也像其他人一样很兴奋地想看看源码是什么样的.然而,在看到源码的第一眼,我 ...
- javascript 匿名函数及闭包----转载
网上很多解释,我无法理解,我想知道原理...这篇文章应该可以透彻一点Query片段:view plaincopy to clipboardprint? (function(){ //这里忽略 ...
- [从jQuery看JavaScript]-匿名函数与闭包(Anonymous Function and Closure)
http://blog.csdn.net/natineprince/article/details/4759533 jQuery片段: (function(){ //这里忽略jQuery所有实现 ...
- javascript匿名函数及闭包深入理解及应用
1.匿名函数 函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途.匿名函数:就是没有函数名的函数. 1.1 函数的定义,首先简单介绍一下函数的定义,大致可分为三种方式 第一种: ...
随机推荐
- 重要:Linux下IDE--KDevelop (用来跟踪调试C++) Ubuntu下QT4开发环境的搭建及初体验
Linux下安装Qt4有两大问题,一是环境变量,二是IDE(集成开发环境).安装Qt4也有两种方法,一种是apt-get,一种是下载源码包,而后 一种方法已经人证实是最有可能不好使的方法.所以我最终采 ...
- 逻辑回归的相关问题及java实现
本讲主要说下逻辑回归的相关问题和详细的实现方法 1. 什么是逻辑回归 逻辑回归是线性回归的一种,那么什么是回归,什么是线性回归 回归指的是公式已知,对公式中的未知參数进行预计,注意公式必须是已知的,否 ...
- C#:加载Excel(待补充)
string strConn; strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + &qu ...
- poi读取excel元素
Java读取excel元素 忽略元数据末尾回到原数据开始处 pom文件设置 <dependency><groupId>org.apache.poi</groupId> ...
- hibernate中一对一映射
一.hibernate中一对一映射有两种 1 主键方式,一张表的主键是通过另一张表的主键生成的 2 外键方式,一张表添加外键引用另一张表的主键,并添加唯一unique约束 二.下面进行简单例子,用户和 ...
- [转]sql:除非另外还指定了 TOP 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询
执行sql语句: select * from ( select * from tab where ID>20 order by userID desc ) as a order by date ...
- Objective-C中的基本数据类型
// // main.m // 01.基本数据类型 // // Created by zhangqs008 on 14-2-13. // Copyright (c) 2014年 zhangqs008. ...
- html使用自我知识点总结
1. 不要忘结束标签 <p>This is a paragraph <p>This is a paragraph 未来的HTML版本号不同意省略结束标签. 2. 没有内容的HT ...
- Quartus调用Modelsim SE避免重复编译Altera器件库的方法
最近用Quartus 15.0配合Modelsim SE 10.4的64位版本,简直就是闪电一般的仿真速度.但是众所周知,SE版本最大的问题就是每次由Quartus自动调用时,都要重新编译所使用的器件 ...
- mysql 主主复制(双主复制)binlog-do-db
[root@DB ~]# grep "binlog-do-db" /etc/my.cnf binlog-do-db = test [root@DB-S ~]# grep " ...