首页 > 代码库 > Javascript---this

Javascript---this

为了解开JavaScript 中 this这个该死 的神秘面孔
连续三天上网查资料,终于有那么一丝丝头绪从脑海闪过
最终搞清楚了这个this黑盒子的第一个机关
为了不让之前的努力及其推断过程被没用的记忆冲刷掉。。。
只好写写日志 随便总结一下 
 

就酱。。。可以启程了  

这里研究this 是针对在对象函数内使用时指向:
一般情况下会指向 调用执行当前函数的对象如:

1
var name="window"
var Tom={
  name:"Tom",
  show:function(){alert(this.name)} 
  }
Tom.show();    //Tom

因为Tom对象调用show方法,
所以在show方法中this指向Tom
 
2
var Bob={
  name:"Bob",
  show:function(){alert(this.name);}
  }; 
 
var Tom={
  name:"Tom",
  show:Bob.show
  }; 

Tom.show() ;   //Tom

因为尽管alert(this.name)是在Bob对象环境中声明的,
但该方法是由Tom对象调用执行所以this总是会指向当前执行的对象,而不是声明的对象

以下为特殊情况
当前执行的对象会随着以下情况出现而更改: 
3.
var name="window";
var Tom={
  name:"Tom".
  show:function(){alert(this.name)}
  };

var fun=Tom.show();
fun();            //window

因为show方法将函数体赋值给fun后
执行fun时的对象就不再是Tom,而是全局变量window

4.
var name="window";
var Tom={
  name:"Tom",
  show:function(){alert(this.name)},
  wait:function(){
             var fun=this.show;
             fun();
         }
  };

Tom.wait();  //window
 
首先wait方法由Tom调用 所以this.show中的this指向Tom
然后Tom.show的函数体赋值给fun后,执行fun
此时不再是Tom去调用fun,而是没有对象去调用fun
因此调用的fun的对象就会被默认为window对象 

那么是什么原因导致对象被更改呢?(不卖关子 答案就在下面)

在一个函数里调用其他函数时,其他函数可以看做这个函数的延迟

上面的例子可以这么看待:
wait方法里执行顺序如下
1.fun变量赋值                          //但只是简单的复制Tom.show函数内容,并不会把当前执行的对象复制过来
2.调用函数fun                          //这里只是指导脚本下一步该怎么做, 在这Tom就算完成任务了
最后再执行fun之前赋值的函数内容,
因此fun函数可以看做Tom的延迟 ,所以fun得不到Tom的调用
下面是个反面例子

5.
var name="window";
var Tom={
  name:"Tom",
  show:function(){alert(this.name)},
  wait:function(){
             var that=this;
             that.show();
         }
  };

Tom.wait();  //Tom

这里把wait当前执行的对象 (也就是Tom)给复制过来了
也就是告诉Tom 方法show也由他调用,因此show不算是Tom的延迟
所以wait完成任务后,Tom继续负责show的任务
总之可以看出真正导致当前执行对象被更改的原因----------就是延迟 
而解决更改的对象的方法就是让Tom加班!

加班方法  除了像上面保存当前执行的对象外
还可以如下
6.
var name = "window"
var Bob= {
    name:"Bob",
    show:function(){alert(this.name);}
    };

 var Tom= {name: "Tom"};
 Bob.show();                   //Bob
 Bob.show.apply();             //window
 Bob.show.apply(Tom);          //Tom

当然call()也差不多类似

那么我们现在来研究,除了上面保存函数值后调用该函数值导致的延迟外
还有那些情况是会导致调用延迟 而将当前执行的对象更改为window

7.匿名函数的延迟

var name="window";
var Tom={
  name:"Tom",
  show:function(){alert(this.name)},
  wait:function(){!function(call){call();}(this.show)}
  }
 
Tom.wait();    //Window

8.setTimeout、setInterval函数延迟

var name="window";
var Tom={
  name:"Tom",
  show:function(){alert(this.name)},
  wait:function(){setTimeout(this.show,1000)}
  }
 
Tom.wait();    //window
 
这里只以.setTimeout为例子

貌似能延迟的就以上几种,日后回来补充

9

对于eval函数,其执行时候似乎没有指定当前对象
但实际上其this并非指向window,
因为该函数执行时的作用域是当前作用域
即等同于在该行将里面的代码填进去。下面的例子说明了这个问题:

var name="window";
var Bob={
  name:"Bob",
  showName: function(){ eval("alert(this.name)"); }
  };
Bob.showName(); //Bob 


另外 虽然函数延迟会导致对象被更改 但是仍然可以在具有延迟的函数 让Tom加班
10. 
var name="window";
var Tom={
  name:"Tom",
  show:function(){alert(this.name)},
  wait:function(){setTimeout(Tom.show,1000)}
  }
 
Tom.wait();    //window

上面把this对象改成Tom,然并卵。。。。依旧返回window
因为Tom.show放在setTimeout第一个参数里
只是将告诉setTimeout函数
执行的函数内容是Tom对象里的show方法,
而没有告诉他这个方法由Tom来执行

以下方法可以告诉他
11.
var name="window"
var  Tom ={  
    name : "Tom",  
    show : function(){alert(this.name);},  
    wait:  function(){
    var that=this;
    setTimeout(function(){that.show()},1000)}  
          }

Tom.wait();    //Tom 

12.eval大哥可以登场了。。。

var name="window";
var that;
var Tom={
  name:"Tom",
  show:function(){alert(this.name)},
  wait:function(){that=this;setTimeout("that.show()",1000)}
  }
 
Tom.wait();    //Tom


 也许你会觉得上面的代码没有eval函数的身影
 其实setTimeout第一个参数就是eval环境,也就会指向当前调用执行的对象

Javascript---this