本文实例讲述了JS闭包原理与应用。分享给大家供大家参考,具体如下:
<强>一,先来看一个例子:强>
函数foo () { var=10; 功能栏(){ *=2; 返回一个; } 返回酒吧; } var巴兹=foo ();//baz是酒吧现在引用函数。 console.log(巴兹());//返回20。 console.log(巴兹());//返回40。 console.log(巴兹());//返回80。 var咩咩=foo ();//咩咩的叫声是另一个参考吧。 console.log(咩咩的叫声());//返回20,因为正在使用的一个新副本。 >之前这里使用:http://tools.jb51.net/code/HtmlJsRun测试上述代码,可得到如下运行结果:
一直以来,我都是以为只有用匿名函数才能算是闭包,但是其实不一定要用匿名函数的,就是一般的函数就可以,前提是它得被包含在另一个函数中。
在foo返回后,它的作用域被保存下来了,但只有它返回的的那个函数能够访问这个作用域。在前面的示例中,巴兹和balt各有各的作用域及一个的一个副本,而且只有他们自己能对其进行修改。
其实就是说我们对foo函数的引用的调用并不会对其他引用有任何影响。
<强>二,封装和隐藏信息强>
看了上面的例子,我们可以考虑采用匿名函数来进行封装和隐藏私有变量。
var书=function (newIsbn newTitle, newAuthor){//实现出版//私有属性。 var isbn,标题、作者;//私有方法。 函数checkIsbn (isbn) {//? 返回true; }//特殊方法。 这一点。getIsbn=function () { 返回isbn; }; 这一点。setIsbn=函数(newIsbn) { 如果(! checkIsbn (newIsbn)抛出新的错误('书:无效的ISBN。'); isbn=newIsbn; }; 这一点。getTitle=function () { 返回标题; }; 这一点。setTitle=函数(newTitle) { title=newTitle | |“无标题指定”; }; 这一点。getAuthor=function () { 返回作者; }; 这一点。setAuthor=函数(newAuthor) { 作者=newAuthor | |“没有作者指定”; };//构造函数代码。 this.setIsbn (newIsbn); this.setTitle (newTitle); this.setAuthor (newAuthor); };//公开,没有权利的方法。 书。原型={ 显示:函数(){//? } }; var mybook=新书(“myisbtn”、“mytittle”,“myauthor”); console.log (mybook.getAuthor ()); >之前使用:http://tools.jb51.net/code/HtmlJsRun测试上述代码,可得到如下运行结果:
我们通过在构造器中用var声明了这些变量和checkIsbn函数,因此他们就变成了私有的属性。需要访问这些变量和函数的方法只需要在书中声明即可。这些方法也被陈伟特权方法。而任何不需要访问私有属性的方法都要在<代码> Book.prototype> 代码中声明,例如显示。但这里也存在个问题:就是每生成一个新的对象实例都将为每一个私有方法和特权方法生成一个新的副本。这会比其他做法耗费更多内存,因此只宜用在真正需要私有成员的场合。另外,这种模式也不适合派生子类,因为派生的子类并不能访问超类的任何私有属性和方法。故在JavaScript中用闭包实现私有成员导致派生问题被称为“继承破坏封装”。
<强>三,改进强>
这里与上一种大体类似,但是也有一些重要的区别。这里私有成员和特权成员仍被声明在构造器中,但是构造器已经变成一个内嵌函数了,并且被作为包含它的函数的返回值赋给变量的书。这就是创建了一个闭包,你可以把静态的私有成员函数声明在里面。
checkIsbn函数被设置为静态方法,是因为没必要为每个实例都生成这个方法的一个副本。此外还有静态属性numBooks限制了构造器总的调用次数
var书=(函数(){//私有静态属性。 var numOfBooks=0;//私有静态方法。 函数checkIsbn (isbn) {//? 返回true; }//构造函数返回。 返回函数(newIsbn newTitle newAuthor){//实现出版//私有属性。 var isbn,标题、作者;//特殊方法。 这一点。getIsbn=function () { 返回isbn; }; 这一点。setIsbn=函数(newIsbn) { 如果(! checkIsbn (newIsbn)抛出新的错误('书:无效的ISBN。'); isbn=newIsbn; }; 这一点。getTitle=function () { 返回标题; }; 这一点。setTitle=函数(newTitle) { title=newTitle | |“无标题指定”; }; 这一点。getAuthor=function () { 返回作者; }; 这一点。setAuthor=函数(newAuthor) { 作者=newAuthor | |“没有作者指定”; };//构造函数代码。 numOfBooks + +;//跟踪多少本书已被实例化//私有的静态属性。 如果(numOfBooks比;1)把新的错误(用书:alt=" JS闭包原理与应用经典示例">JS闭包原理与应用经典示例