Javascript 中闭包(Closure)的探索(三)私有函数中的this

在上一篇文章中,私有函数里给公有变量this.publicMem 赋值并没有达到预期的效果。(示例代码参见Javascript 中闭包(Closure)的探索(二)-私有变量和函数

原因在于每个函数被调用时,会产生自己的scope,在此scope中,会生成自己函数内使用的变量,方法等等。

对于公有的变量和方法(如上篇文章例子中的this.publicMem和this.callprivateFunc等)会在函数ClassFunc被new出来时一起加入到ClassFunc的scope中,因此在函数callprivateFunc中的this指针就是指向当前new出来的ClassFunc对象。

而对于私有函数privateFunc,是在被调用时才形成自己的scope的,由于这个函数不在ClassFunc的scope中,因此其中的this指针就是指向全局的window对象。

验证代码如下:

<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!";
            // 相当于给window对象的publicMem属性赋值
            // 因为当前window对象不存在publicMem属性,所以新建了publicMem属性。
            // 此时test对象的this.publicMem没变
            this.publicMem = "public changed!";
        }

        this.callprivateFunc = function() {
            privateFunc();
        }
    }

    function closureTestClick() {
        var test = new ClassFunc();
        // 变更前
        alert("privateMem=" + test.getprivateMem());
        alert("publicMem=" + test.publicMem);
        // 此时window.publicMem为undefined
        alert("publicMem=" + window.publicMem);
        test.callprivateFunc(test);
        // 变更后
        alert("privateMem=" + test.getprivateMem());
        alert("publicMem=" + test.publicMem);
        // 此时window.publicMem为"public changed!"
        alert("publicMem=" + window.publicMem);
    }
</script>

如果需要在私有函数中利用this操作当前对象test,而非window对象。可以利用javascript内置的两个方法callapply,即显示的将对象传递给私有函数privateFunc。

代码如下:

<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!";
                this.publicMem = "public changed!";
            }

            this.callprivateFunc = function() {
                privateFunc.apply(this);
                //或者
                //privateFunc.call(this);
            }
        }

        function closureTestClick() {
            var test = new ClassFunc();
            // 变更前
            alert("privateMem=" + test.getprivateMem());
            alert("publicMem=" + test.publicMem);
            // 此时window.publicMem为undefined
            alert("publicMem=" + window.publicMem);
            test.callprivateFunc(test);
            // 变更后
            alert("privateMem=" + test.getprivateMem());
            // 此时test.publicMem被改变了
            alert("publicMem=" + test.publicMem);
            // 此时window.publicMem为undefined
            alert("publicMem=" + window.publicMem);
        }
    </script>

因此,我们在js中使用私有函数的时候一定要注意这个特点,这也是js和其他真正面向对象的语言(C#,java等)的区别之一吧!

如有理解不对的地方,还希望各位不吝指教!

原文地址:https://www.cnblogs.com/wang_yb/p/1729646.html