Cui.Liqiang

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

  这两天做javascript的时候遇到一些scope方面的问题。然后就搜搜试试搞了一阵子。得到以下一些有趣的结论。为了清楚起见,下面使用代码配合文字来说明下问题。

1 function ClassA(){
2 this.fun1 = function(){
3 this.fun11 = function(){
4 this.fun2();
5 }
6 this.var1 = 'var1';
7 this.fun11();
8 window.setTimeout(this.fun11(), 1000);
9 }
10
11 this.fun2 = function(){
12 this.fun21 = function(){}
13 this.var2 = 'var2';
14 }
15 ca = new ClassA();

 

1,在用this.fun的形式定义的函数里面如果再嵌套使用this定义函数或者变量,该this仍然是最高层的this。

 

  比如在这个例子中,在fun1, fun2, fun11, fun21中都可以用this指针调用到其他三个函数。但前提是调用前该被调用的函数所在的行数需要被解释器解释过.上面ca是ClassA的一个实例。如果想要调用fun21函数,必须先调用一次fun2函数一次,否则就会看到undefined method的结果。对于this指定的变量,规则亦然。

 

2,在this定义的函数中,可以使用this或者直接使用var来定义变量或者函数。规则是从this定义的函数可以访问到外层的两种变量,但是用var定义的函数只能访问var定义的变量。

 

3,一般情况下,如第一条所陈述,在所有的this定义的函数中访问this指针都是ca实例变量的this。但是在setTimeout或者setInterval等类似的需要传入函数指针的函数,情况有所不同。在该回调函数被调用的时候,其中的this指针就不再是原来的this了,而是通通变成了DOM的window对象。

  如上面的代码实例。第七行的调用方法没问题可以访问到fun2(),但第八行的代码就无法被正确执行了。当1000毫秒之后,fun11被触发的时候,其中的this就变成window了。你可以在这个函数中直接访问window的属性或者方法,而不使用window.的前缀,来进行检验该规则正确性。

  setTimeout和setInterval这两个函数的第一个参数除了可以是一个函数指针之外,还可以是一个内联函数,或者是一段用引号引起来的script,无论哪种形式都和上面所提到的有一样的结果,即其中的this都指向了window对象。

  促成本文最初的需求就是想要在这样一个场景中真正的访问到对象实例的this而不是window对象。最终得到一个看起来不是特别优雅但是还算有效的方法如下:

1 function ClassA(){
2 this.fun1 = function(){
3 var self = this;
4 var fun11 = function(){
5 //this.fun2();
6   self.fun2();
7 }
8 window.setTimeout(this.fun11(), 1000);
9 }
10
11 this.fun2 = function(){
12 }
13 ca = new ClassA();
14 ca.fun1();
在第三行使用self保存下this指针。然后在使用第六行的代码替换第5行的,就大功告成了~~

  希望过路的能留下更好的方法下来。

posted on 2010-11-29 23:47  Cui.Liqiang  阅读(475)  评论(0编辑  收藏  举报