某某茶叶有限公司欢迎您!
金沙棋牌在线 > 服务器&运维 > javascript闭包的理解和实例_javascript技巧_脚本之家

javascript闭包的理解和实例_javascript技巧_脚本之家

时间:2019-11-27 20:39

官方解释 “闭包”是一个拥有许多变量和绑定了这些变量的环境表达式,因而这些变量也是环境表达式的一部分。 通俗解释 Javascript中所有的函数都是一个闭包。不过一般来说,嵌套的function产生的闭包更为强大,也是大部分时候我们所说的“闭包”。看如下代码: 复制代码 代码如下:

本文实例讲述了javascript闭包功能与用法。分享给大家供大家参考,具体如下:

顺便提示一下: 词法作用域:变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通过静态分析就能确定,因此词法作用域也叫做静态作用域。 with和eval除外,所以只能说JS的作用域机制非常接近词法作用域。 下面是一个简单的使用全局变量的闭包实例: 复制代码 代码如下: var sWord="Hello,Welcome to web前端开发工程师的博客,请多多指教。" function disWord; } disWord(); 解析:脚本载入到内存的时候,disWord并没有计算sWord的值,而是函数disWord调用的时候执行了sWord的计算。 下面是函数中定义另一个函数的闭包实例: 复制代码 代码如下: var iNum=10; function add{ function doAdd(){return num1+num2+iNum;} return doAdd(); } 解析:内部函数doAdd是个闭包,它将获取传入参数num1,num2和全局变量iNum的值,doAdd不接受参数,add最后一步调用doAdd,请两个参数和全局变量求和返回,可以看得出doAdd使用的值是在执行环境中获得的。 下面是在网上找的几个例子,理解词法作用域和闭包 复制代码 代码如下: 、案例一 /*全局域下的一段代码*/ function a; }; a; 疑问:上面的代码会输出什么呢? 答案:10。 具体执行过程 a 函数有一个形参 i,调用 a 函数时传入实参 10,形参 i=10 接着定义一个同名的局部变量 i,未赋值 alert 输出 10 思考:局部变量 i 和形参 i 是同一个存储空间吗? 、案例二 复制代码 代码如下: 1 /*全局域下的一段代码*/ 2 function a; 4 alert; //arguments[0]应该就是形参 i 5 var i = 2; 6 alert; 7 alert; 8 }; 9 a; 疑问:上面的代码又会输出什么呢? 答案:10,10,2,2 具体执行过程 函数有一个形参i,调用 a 函数时传入实参 10,形参 i=10 第一个 alert 把形参 i 的值 10 输出 第二个 alert 把 arguments[0] 输出,应该也是 i 接着定义个局部变量 i 并赋值为2,这时候局部变量 i=2 第三个 alert 就把局部变量 i 的值 2 输出 第四个alert再次把 argumentsa[0] 输出 思考:这里能说明局部变量 i 和形参 i 的值相同吗? 、案例三 复制代码 代码如下: /*全局域下的一段代码*/ function a { var i = i; alert 疑问:上面的代码又又会输出什么呢? 答案:10 具体执行过程 第一句声明一个与形参 i 同名的局部变量 i,根据结果我们知道,后一个 i 是指向了 形参 i,所以这里就等于把形参 i 的值 10 赋了局部变量 i 第二个 alert 当然就输出 10 思考:结合案列二,这里基本能说明局部变量 i 和形参 i 指向了同一个存储地址! 、案例四 复制代码 代码如下: /*全局域下的一段代码*/ var i=10; function a; var i = 2; alert; 疑问:上面的代码又会输出什么呢? 答案:undefined, 2 具体执行过程 第一个alert输出undefined 第二个alert输出 2 思考:到底怎么回事儿? 看到上面的几个例子,你可能会想到底是怎么执行的呢?执行的细节又是怎么样的呢? JS 引擎的工作方式是怎样的呢? 解析过程 、执行顺序 编译型语言,编译步骤分为:词法分析、语法分析、语义检查、代码优化和字节生成。 解释型语言,通过词法分析和语法分析得到语法分析树后,就可以开始解释执行了。这里是一个简单原始的关于解析过程的原理,仅作为参考,详细的解析过程还需要更深一步的研究 javascript的执行过程,如果一个文档流中包含多个script代码段(用script标签分隔的js代码或引入的js文件),它们的运行顺序是: 步骤1. 读入第一个代码段(js执行引擎并非一行一行地执行程序,而是一段一段地分析执行的) 步骤2. 做词法分析和语法分析,有错则报语法错误,并跳转到步骤5 步骤3. 对定义做“预解析“ 步骤4. 执行代码段,有错则报错 步骤5. 如果还有下一个代码段,则读入下一个代码段,重复步骤2 步骤6. 结束 、特殊说明 全局域域下所有JS代码可以被看成是一个“匿名方法“,它会被自动执行,而此“匿名方法“内的其它方法则是在被显示调用的时候才被执行 、关键步骤 上面的过程,我们主要是分成两个阶段 解析:就是通过语法分析和预解析构造合法的语法分析树。 执行:执行具体的某个function,JS引擎在执行每个函数实例时,都会创建一个执行环境和活动对象(它们属于宿主对象,与函数实例的生命周期保持一致) 在这里有更详细的实例分析资料://www.jb51.net/article/24547.htm

在ECMAScript中,在函数声明处向函数外部看到的声明的所有变量,在函数内部都能访问到它们的最终值

这段脚本在执行完var c=a()之后,变量c实际上就指向了函数b,b中用到了变量i,再执行c()后就会弹出一个窗口显示i的值。这段代码其实就是一个闭包,为什么?因为函数a外的变量c引用了函数a内部的函数b。 Javascript的垃圾回收机制 由于javascript特殊的垃圾回收机制,才导致了闭包的产生。Javascript垃圾回收机制的大体规则如下: 在javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象相互引用,而不再被第3者引用,那么这两个互相引用的对象也会被回收。而在上述的脚本中,函数a被b引用,函数b又被函数a外的c所引用,这就是为什么函数a执行后不被回收的原因。 闭包的应用场景 1. 保护函数内的变量安全。以上面的例子为例,函数a中变量i只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。 2. 在内存中维持一个变量。依然如上面的例子,由于闭包,函数a中的i一直存在于内存中,因此每次执行c(),i都会加1。 3. 通过保护变量的安全实现JS私有属性和私有方法。如下,私有属性和私有方法在Constructor外是无法访问的: 复制代码 代码如下: function Constructor{ var that = this; var membername = value; function membername{…} }

理解闭包

闭包函数只能访问变量的最终值!!!

闭包这个东西,确实是很麻烦。之前我自己的理解也是有一点误差,所以今天将文章修改修改,争取将自己的理解进一步准确化。

eg:

闭包说得通熟易懂一点,就是指有权访问另一个函数作用域的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另外一个函数,并返回

function fnTest { for (var i=0;i < arr.length;i++) { arr[i]=function () { alert; }; }}var arr = [0,1,2,3];fnTest;for (var i=0;i < arr.length;i++) {arr[i](); //始终输出4还有一个undefined因为函数退出后,i值为4,所以访问到的值只有4

我们这里举一个例子来说明,首先我们在函数f1内部定义一个函数f2。

//结果会连续弹出4个"4|undefined”}

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

不但在闭包中可以访问闭包外的变量值,而且还可以设置它的值

f2可以访问f1的作用域,反过来就不行了。现在我们想访问f1中的n,在外层却访问不到,怎么办呢?将f2作为f1的返回值就可以了:

eg: