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内置的两个方法call和apply,即显示的将对象传递给私有函数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等)的区别之一吧!
如有理解不对的地方,还希望各位不吝指教!