Javascript 中闭包(Closure)的探索(二)-私有变量和函数

利用匿名函数形成闭包可以在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.publicMemthis已经不是指向test这个js对象了。

关于this的指向为什么会变,参见我的第三篇文章,介绍javascript的scope的。

本例中为了能够修改testpublicMem属性,有两个方法:

其一,也是常用的,直接在外部修改publicMem,因为publicMem是公有变量。

test.publicMem = "public changed!";

其二,在函数callprivateFuncprivateFunc中增加一个参数,显示的传入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>
posted @ 2010-05-06 17:40  wang_yb  阅读(906)  评论(1编辑  收藏  举报