利用匿名函数形成闭包可以在javascript中实现面向对象语言中的访问权限控制。即在javascript中也能实现私有变量。
参考网址:http://www.crockford.com/javascript/private.html
1.构造私有变量和公有变量
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>JsClosure2</title>
<script type="text/javascript">
function ClassFunc() {
this.publicMem = "public";
var privateMem = "private";
}
function closureTestClick() {
var test = new ClassFunc();
alert(test.publicMem);
alert(test.privateMem);
}
</script>
</head>
<body>
<input type="button" value="closureTest" onclick="closureTestClick()" />
</body>
</html>
<html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>JsClosure2</title> <script type="text/javascript"> function ClassFunc() { this.publicMem = "public"; var privateMem = "private"; } function closureTestClick() { var test = new ClassFunc(); alert(test.publicMem); alert(test.privateMem); } </script> </head> <body> <input type="button" value="closureTest" onclick="closureTestClick()" /> </body> </html>
结果:alert(test.publicMem);可以正常显示,alert(test.privateMem);显示“undefined”。
结果分析:通过var定义的私有变量外界无法访问,如果要外界可以访问,需要构造get,set方法。
<script type="text/javascript"> function ClassFunc() { this.publicMem = "public"; var privateMem = "private"; this.getprivateMem = function() { return privateMem; } this.setprivateMem = function(val) { privateMem = val; } } function closureTestClick() { var test = new ClassFunc(); alert(test.getprivateMem()); test.setprivateMem("private changed!"); alert(test.getprivateMem()); } </script>
结果:如预期的一样显示“private”和“private changed!”。
2.私有函数
与私有变量的定义类似,不是通过this来定义的函数都是私有函数。
私有函数外部无法调用,但是可以通过内部的公有函数来调用。
测试代码如下:
<script type="text/javascript"> function ClassFunc() { this.publicMem = "public"; var privateMem = "private"; this.getprivateMem = function() { return privateMem; } this.setprivateMem = function(val) { privateMem = val; } function privateFunc() { privateMem = "private changed!"; // 此处的赋值并没有如预期的那样给test.publicMem成员赋值 this.publicMem = "public changed!"; } this.callprivateFunc = function() { privateFunc(); } } function closureTestClick() { var test = new ClassFunc(); // 变更前 alert("privateMem="+test.getprivateMem()); alert("publicMem=" + test.publicMem); test.callprivateFunc(); // 变更后 alert("privateMem=" + test.getprivateMem()); alert("publicMem=" + test.publicMem); } </script>
变更后的结果privateMem如预期一样,而publicMem仍然是“public”,并没有改变。
这是因为函数privateFunc() 中this.publicMem 的this已经不是指向test这个js对象了。
关于this的指向为什么会变,参见我的第三篇文章,介绍javascript的scope的。
本例中为了能够修改test的publicMem属性,有两个方法:
其一,也是常用的,直接在外部修改publicMem,因为publicMem是公有变量。
test.publicMem = "public changed!";
其二,在函数callprivateFunc 和privateFunc中增加一个参数,显示的传入test对象。
<script type="text/javascript"> function ClassFunc() { this.publicMem = "public"; var privateMem = "private"; this.getprivateMem = function() { return privateMem; } this.setprivateMem = function(val) { privateMem = val; } function privateFunc(obj) { privateMem = "private changed!"; // 直接给obj.publicMem赋值 obj.publicMem = "public changed!"; } this.callprivateFunc = function(obj) { privateFunc(obj); } } function closureTestClick() { var test = new ClassFunc(); // 变更前 alert("privateMem="+test.getprivateMem()); alert("publicMem=" + test.publicMem); test.callprivateFunc(test); // 变更后 alert("privateMem=" + test.getprivateMem()); alert("publicMem=" + test.publicMem); } </script>