认识JavaScript中的闭包和匿名函数

简介: 认识JavaScript中的闭包和匿名函数

想要学习闭包先来看看什么是匿名函数吧!  


(一)匿名函数


匿名函数就是没有名字的函数。他有两种声明方式:  

1.典型的函数声明:  

function functionName(arg0,arg1,arg2){  
    //函数体  
}  
2.函数表达式:  
var functionName = function(arg0,arg1,arg2){  
    //函数体  
}

虽然这两种方式在逻辑上市等价的,但是他们还是存在区别的。  

区别1:前者会在代码执行以前被加载到作用域中,而后者则是在代码执行到那一行的时候才会有意义。  

区别2:前者会给函数指定一个名字,而后者则是创建一个匿名函数,然后将这个匿名函数赋给一个变量。  

换句话说上面第二个例子:创建了一个带有3个参数的匿名函数,然后把这个匿名函数赋给了变量functionName,并没有给匿名函数指定名字。

 

(二)闭包  


书上定义是这么说的:指有权访问另一个函数作用域中的变量的函数  

可是这种说法令新手难以理解。其实,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。  

1.那我先来说说为什么要有闭包这么个概念吧,它产生的意义是什么呢?  

(1)首先我们学过前面的作用域了,知道了一个概念:函数内部可以直接读取全局变量。  

那么看代码:  

var n=999;  
function f1(){  
    alert(n);  
}  
f1(); // 999

(2)然后另外一个概念:在函数外部自然无法读取函数内的局部变量  

那么再看代码:  

function f1(){  
  var n=999;  
}  
alert(n); //输出错误

(3)这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!(我们以前也提到过的!)  

function f1(){  
  n=999;  
}  
f1();  
alert(n); // 999

下面关键的来了!:那就是如何从外部读取局部变量呢?  

那就是在函数的内部,再定义一个函数。(也就是闭包!!)  

function f1(){  
  var n=999;  
  function f2(){  
    alert(n); // 999  
  }  
}

在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!来看代码:  

function f1(){  
  var n=999;  
  function f2(){  
    alert(n);  
  }  
   return f2;  
}  
var result = f1();  
result(); //999

这段代码与上面的不同点就是把f2函数作为了一个返回值,然后在调用它。这时你肯定在想最后两行什么意思啊?其实开始我也没闹明白,经过高人指点,其实这最后两行的意思就是要调用f2这个函数的返回值。这两行如果我改写一下是不是更容易明白了呢?  

var result = f1();  
result();

合并成为:f1()();其实结果是一样的  

也可以更好的说明f2这个闭包的作用是:通过把它作为返回值(因为它能访问函数f1内的局部变量),然后从全局环境中调用这个返回值,这样自然就达到了我们的目的---从全局作用域中读取局部函数内的变量!  

2.既然知道了闭包的意义,下面就来了解下闭包的用途吧!  

(1)闭包的第一个用途,其实上面已经提到了,就是产生它意义:可以读取函数内部的变量  

(2)闭包的第二个用途,那就是:可以让这些变量的值始终保持在内存中  

第二个用途怎么理解呢?来看代码:  

function f1(){  
  var n=999;  
  nAdd=function(){  
     n+=1  
  }  
  function f2(){  
    alert(n);  
  }  
  return f2;  
}  
var result=f1();   //把f1函数的返回值(而这个返回值是函数f2的形式)给result  
result();          // 999   输出这个f2的返回值  
nAdd();            //调用nAdd函数  
result();          // 1000  这里就是闭包的第二个用途:f2这个闭包会让变量n的值始终保存在内存中

光靠代码来理解第二种用途,好像没有什么说服力,下面就用画图的方法来让大家更深刻的理解!!  


第二种用途其实就和作用域链产生联系了,解释下:  

闭包f2从f1函数中被返回后,它的作用域链被初始化为包含f1函数的活动对象和全局变量对象(黑线部分)。这样f2就可以访问在f1()函数中定义的所有变量。更为重要的是就算f1()被执行完毕后,它的活动对象也不会被销毁,因为如图f2这个闭包还在引用f1函数的活动对象,这也就是为什么上述第二种用途的原因:闭包会让变量始终保存在内存中,直到闭包被摧毁。


目录
相关文章
|
27天前
|
JavaScript
闭包(js的问题)
闭包(js的问题)
12 0
|
2月前
|
设计模式 JavaScript 前端开发
js开发:请解释闭包(closure)是什么,以及它的用途。
闭包是JavaScript中的关键特性,允许函数访问并操作外部作用域的变量,常用于实现私有变量、模块化和高阶函数。私有变量示例展示了如何创建无法外部访问的计数器;模块化示例演示了封装私有变量和函数,防止全局污染;高阶函数示例则说明了如何使用闭包创建能接收或返回函数的函数。
16 2
|
2月前
|
存储 缓存 JavaScript
|
2月前
|
自然语言处理 JavaScript 前端开发
探索JavaScript中的闭包:理解其原理与实际应用
探索JavaScript中的闭包:理解其原理与实际应用
20 0
|
2月前
|
自然语言处理 JavaScript 前端开发
深入理解JS的执行上下文、词法作用域和闭包(中)
深入理解JS的执行上下文、词法作用域和闭包(中)
|
2月前
|
存储 自然语言处理 JavaScript
深入理解JS的执行上下文、词法作用域和闭包(上)
深入理解JS的执行上下文、词法作用域和闭包(上)
|
3天前
|
自然语言处理 JavaScript 前端开发
闭包对于javascript中有什么作用
JavaScript中的闭包有多种用途,如数据封装和私有化、函数工厂及保持状态。闭包能创建私有变量和函数,防止外部访问,实现清晰的代码接口。
|
6天前
|
测试技术
js_防抖与节流(闭包的使用)
js_防抖与节流(闭包的使用)
13 0
|
2月前
|
JavaScript 前端开发 Java
深入剖析 JavaScript 闭包
深入探讨JavaScript闭包,了解其定义、特性、优缺点及作用。闭包是函数与其引用环境的组合,允许内层函数访问外层作用域,常驻内存可能导致内存泄露。优点包括创建私有变量,缺点则涉及内存使用。闭包在变量搜索中遵循从内到外的规则,并影响变量的作用域和生存周期。理解闭包有助于优化代码并避免性能问题。
21 1
|
2月前
|
自然语言处理 前端开发 JavaScript
深入理解JavaScript中的闭包与作用域链
在JavaScript编程中,闭包和作用域链是两个非常重要的概念,它们对于理解代码的执行过程和解决一些特定问题至关重要。本文将深入探讨JavaScript中闭包和作用域链的原理和应用,帮助读者更好地理解这些概念并能够在实际项目中灵活运用。