在上一篇文章中,私有函数里给公有变量this
.publicMem
赋值并没有达到预期的效果。(示例代码参见Javascript 中闭包(Closure)的探索(二)-私有变量和函数)
原因在于每个函数被调用时,会产生自己的scope,在此scope中,会生成自己函数内使用的变量,方法等等。
对于公有的变量和方法(如上篇文章例子中的this.publicMem和this.callprivateFunc等)会在函数ClassFunc被new出来时一起加入到ClassFunc的scope中,因此在函数callprivateFunc中的this指针就是指向当前new出来的ClassFunc对象。
而对于私有函数privateFunc,是在被调用时才形成自己的scope的,由于这个函数不在ClassFunc的scope中,因此其中的this指针就是指向全局的window对象。
验证代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
<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。
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
<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等)的区别之一吧!
如有理解不对的地方,还希望各位不吝指教!
本文转自wang_yb博客园博客,原文链接:http://www.cnblogs.com/wang_yb/archive/2010/05/07/1729646.html,如需转载请自行联系原作者