JavaScript中的匿名函数及函数的闭包
1、匿名函数
2、闭包
3、举例
4、注意
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);
}
4.2 内存泄露
使用闭包十分容易造成浏览器的内存泄露,严重情况下会是浏览器挂死,感兴趣的的话可以参考:http://www.cnblogs.com/rainman/archive/2009/03/07/1405624.html。
分享到:
相关推荐
在讨论JavaScript编程语言时,匿名函数和闭包是两个重要的概念,它们在函数式编程和模块化代码设计中扮演着核心角色。匿名函数是没有具体名称的函数,它们可以是独立的,也可以是表达式的一部分,通常用于定义临时...
**匿名函数**和**闭包**都是JavaScript中非常强大的特性。通过灵活运用这些概念,可以编写出更加高效和可维护的代码。然而,需要注意的是,由于闭包会导致函数的作用域被持续保留,因此过度使用闭包可能会导致内存...
JavaScript中的闭包、匿名函数和作用域链是编程中至关重要的概念,它们是理解JavaScript运行机制的关键。在本文中,我们将深入探讨这三个概念,并通过实际示例来展示它们的运用。 首先,我们来讨论“闭包”。闭包是...
在JavaScript中,匿名函数、函数直接量和闭包是三种非常重要的概念,它们在编程实践中有着广泛的应用。让我们逐一深入探讨这些概念。 1. **匿名函数**: 匿名函数是指没有名字的函数,通常作为表达式的一部分存在...
- 函数式编程:匿名函数是JavaScript函数式编程的核心,例如高阶函数、闭包、柯里化等概念都离不开匿名函数。 5. 匿名函数的优缺点: - 优点:提高代码的封装性,减少全局变量,提高代码的安全性和可维护性,适用...
在闭包中,`this`的指向取决于调用上下文。在上述的`getUserFunction`示例中,`this`在闭包内指向的是`window`,而不是`obj`,因为闭包不是一个对象的方法。如果想让`this`指向`obj`,可以使用`.call`或`.apply`方法...
在JavaScript中,任何函数都可以形成闭包,包括匿名函数。例如: ```javascript function outer() { var counter = 0; return function() { counter++; console.log(counter); }; } var increment = outer();...
JavaScript中的匿名函数是一种不具有名称的函数,它们主要通过函数表达式或Function构造函数来创建。匿名函数在JavaScript中有着广泛的应用,特别是在避免全局变量污染、实现模块化和函数式编程等方面。以下是对匿名...
JavaScript中的匿名函数和闭包是两个非常重要的概念,它们在函数式编程和模块化开发中起着关键作用。 首先,让我们来理解匿名函数。匿名函数,顾名思义,是没有名称的函数。在JavaScript中,我们可以直接定义一个不...
JavaScript中的匿名函数是一种没有函数名的函数,它们可以作为一个表达式的结果或者被赋值给一个变量,也可以在其他函数内部定义并立即执行。这使得它们在处理一次性任务或需要封装私有变量时非常有用。 匿名函数最...
### JavaScript中的匿名函数、函数直接量与闭包 #### 匿名函数与函数直接量 在JavaScript编程语言中,函数是一等公民,这意味着函数可以作为参数传递,也可以被其他函数返回。这种特性使得函数可以非常灵活地应用...
更复杂的是,可以使用`new Function`构造函数创建函数,或者定义匿名函数,如`(function(){ //TODO here})()`,这常用于模块化隔离。内嵌函数(内部函数)允许访问外部函数的变量,这是闭包的基础。 当我们谈论函数...
### JavaScript中匿名函数的创建与调用方法分析 #### 一、概述 在JavaScript中,函数是一等公民,这意味着函数可以作为参数传递给其他函数,也可以作为其他函数的返回值。这种灵活性使得JavaScript中的函数非常强大...
直接引用时需要注意闭包中变量的生命周期问题,而通过匿名函数捕获变量可以有效解决这一问题,使得每个闭包都能拥有外部变量的一个独立副本。在实际开发中,我们应该根据不同的场景选择合适的闭包使用方式,以提高...
JavaScript是一种广泛应用于前端开发的脚本语言,其中匿名函数和闭包是JavaScript编程中非常重要的概念。通过理解这两者的工作原理和使用方法,可以极大地提升编程能力和代码的模块化、封装化程度。 首先来看匿名...