JavaScript 闭包
什么是闭包
闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。闭包的特点:
1. 作为一个函数变量的一个引用,当函数返回时,其处于激活状态。
2. 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。
简单的说,Javascript允许使用内部函数---即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。
闭包的几种写法和用法
第一种写法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> <script type="text/javascript"> function Circle(r) { this.r = r; } Circle.PI = 3.14159; Circle.prototype.area = function() { return Circle.PI * this.r * this.r; } var c = new Circle(1.0); alert(c.area()); </script> </head> <body> </body> </html>
这种写法没什么特别的,只是给函数添加一些属性。
第二种写法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> <script type="text/javascript"> var Circle = function() { var obj = new Object(); obj.PI = 3.14159; obj.area = function( r ) { return this.PI * r * r; } return obj; } var c = new Circle(); alert( c.area( 1.0 ) ); </script> </head> <body> </body> </html>
这种写法是声明一个变量,将一个函数当作值赋给变量。
第三种写法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> <script type="text/javascript"> var Circle = new Object(); Circle.PI = 3.14159; Circle.Area = function( r ) { return this.PI * r * r; } alert( Circle.Area( 1.0 ) ); </script> </head> <body> </body> </html>
这种方法最好理解,就是new 一个对象,然后给对象添加属性和方法。
第四种写法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> <script type="text/javascript"> var Circle={ "PI":3.14159, "area":function(r){ return this.PI * r * r; } }; alert( Circle.area(1.0) ); </script> </head> <body> </body> </html>
这种方法使用较多,也最为方便。var obj = {}就是声明一个空的对象
Javascript闭包的用途
事实上,通过使用闭包,我们可以做很多事情。比如模拟面向对象的代码风格;更优雅,更简洁的表达出代码;在某些方面提升代码的执行效率。
1、匿名自执行函数
2、结果缓存
3、封装
4、实现类和继承
JavaScript 内嵌函数
所有函数都能访问全局变量。
实际上,在 JavaScript 中,所有函数都能访问它们上一层的作用域。
JavaScript 支持嵌套函数。嵌套函数可以访问上一层的函数变量。
该实例中,内嵌函数 plus() 可以访问父函数的 counter 变量:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <p id="demo">0</p> <script> document.getElementById("demo").innerHTML = add(); function add() { var counter = 0; function plus() {counter += 1;} plus(); return counter; } </script> </body> </html>
如果我们能在外部访问 plus() 函数,这样就能解决计数器的困境。
我们同样需要确保 counter = 0 只执行一次。
这里就需要闭包。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <button type="button" onclick="myFunction()">计数!</button> <p id="demo">0</p> <script> var add = (function () { var counter = 0; return function () {return counter += 1;} })(); function myFunction(){ document.getElementById("demo").innerHTML = add(); } </script> </body> </html>
实例解析
变量 add 指定了函数自我调用的返回字值。
自我调用函数只执行一次。设置计数器为 0。并返回函数表达式。
add变量可以作为一个函数使用。非常棒的部分是它可以访问函数上一层作用域的计数器。
这个叫作 JavaScript 闭包。它使得函数拥有私有变量变成可能。
计数器受匿名函数的作用域保护,只能通过 add 方法修改。
闭包是可访问上一层函数作用域里变量的函数,即便上一层函数已经关闭。