javascript使用闭包模拟对象的私有属性和方法
前端之家收集整理的这篇文章主要介绍了
javascript使用闭包模拟对象的私有属性和方法,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_403_0@最近因为做了一个项目,其中涉及到了js私有方法,这个概念在其语言里面是很常见的,很多语言都有private这个关键字,只要在一个类的前面加上private就表示申明了一个私有方法,但是javascript在面向对象的方面没有那么多的特征,他没有专门的private关键字,。要做到这一点就必须使用js自己的一些特性来变相的完成。
@H_
403_0@首先javascript里面有一个高级特性叫闭包,简单的说js的闭包可以理解成是一种现象或者特性,一般出现在两个
函数嵌套的情况下,看例子:
<div class="jb51code">
<pre class="brush:js;">
function a(){
var eg = 1;
return function(){
alert(eg);
}
}
var c = a();
@H_
403_0@a
函数里返回了一个
函数,返回的
函数被全局作用域下的c接受了,此时因为返回的
函数调用了a
函数里面的eg变量,并且被全局作用域下的变量c引用,此时下形成闭包,a
函数的内存空间不会被收回,这个闭包的理解其实和js的
垃圾回收机制有关,js的
垃圾回收其实是靠引用来计算的,比如我们申明了一个
函数,这个
函数就会有一个引用指向他自己,当
函数运行结束的时候销毁引用,js如果发现没有引用的
函数就会销毁这个
函数的内存空间,
函数也就没有了。我们上面的例子中首先a
函数运行,给eg赋值1,然后返回一个匿名
函数,到此a
函数运行完了,按照原有的理论,此时a
函数应该被销毁,但是此时他返回了一个
函数,这个
函数被全局下的变量c引用,c是不会被销毁的,除非我们手动销毁,而且这个返回的
函数引用了a
函数的变量eg,js引擎会认为eg依然是有用的,因为他仍然在被使用,因此包含eg这个局部变量的
函数a也不会被销毁。
@H_
403_0@闭包的理解可能不是一下讲的通的,这里其实还涉及到一个作用域的问题,我记得以前有人说返回的这个
函数被c接收了,c是在全局作用下的,为什么
调用c的时候会弹出a
函数里面的eg,难道不应该是全局作用域下的eg吗?而且js的
函数作用于是局部的,外部不能访问。其实这里有一个理论,记住就可以,js里的
函数作用域取决于
函数定义的位置,而不是
函数调用的位置,也就是说,
函数在什么地方定义的,他的作用域就决定了,不管他在什么地方
调用,作用域都不会改变,返回的这个匿名
函数是在a
函数里面定义的,所以他的上级作用域就是这个a
函数,而不是全局作用域。
@H_
403_0@这里要说的私有
方法其实和闭包是有关系的,私有
方法在其他语言里面是不被访问到的,除非有专门的接口,js的局部作用域里面的东西在正常情况下也是不能被外部访问到,但是上面例子
显示了,通过闭包的方式可以访问到,这样我们就可以利用这个特性,看例子:
var a = new book();
a.auther//"dava"
a.price// 200
a.page//"wrong"
a._page()// 100
@H_
403_0@这里例子用了一个
函数自动执行,一上来就执行了一个匿名
函数,并且在匿名
函数里面定义了一个局部变量page,然后又返回了一个匿名
函数,并且被全局作用域下的book变量接收,此时使用new
调用book就会
生成一个新对象a。其中auther
属性和price
属性可以直接通过对象访问,因为这些
属性都是new的时候直接定义在返回的对象身上的,而page
属性则没有,因此不能反回,但此时如果我想访问page
属性,那就得依靠闭包了,返回的
函数在外层的匿名
函数里面,因此在返回的
函数身上定义了一个
方法叫_page,这个
方法弹出了page
属性,按照js作用域的关系,当前作用域找不到page,就会到上层作用域去寻找,这样就找到了。通过这种方式我们就把私有
方法和公有
方法区分开了。