zoukankan      html  css  js  c++  java
  • 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>
    
  • 相关阅读:
    sprintf与snprintf
    风雨20年:我所积累的20条编程经验
    istream_iterator, ostream_iterator,copy以及文件序列化
    [转载]关于C++,我觉得好的设计法则
    如何高效地管理时间
    B站上适合程序员的学习资源【赶紧收藏!】
    Redis和Memcached的区别
    Swoole的多进程模块
    Mac OS 查看 ip 地址及 DHCP 各 addr 含义
    mac将phpstorm 从主屏移动到副显示器(解决)
  • 原文地址:https://www.cnblogs.com/wang_yb/p/1729070.html
Copyright © 2011-2022 走看看