首页 Javascript 正文
210

Javascript之this关键字

  • yiqingpeng
  • 2015-05-01
  • 0
  •  
要弄明白this,首先得了解一个概念:执行上下文
执行上下文是一个抽象出来的概念,它是指当控制器转到可执行代码的时候,即会进入到一个执行上下文。
曾经遇到一个题,如下:
var name = "the window";
var obj = {
  name:"the object",
  getFunc: function(){
    console.log(this.name); //1:输出什么?
    return function(){return this.name;};
  }
};
alert( obj.getFunc()());//2:输出什么?
1处输出”the object"很容易理解,但是2处输出“the window”就有些不明所以了。
其实this只有在进入执行上下文的时候才会确定所指对象到底是谁(即this到对象的绑定发生在调用的时候),一般来说this指的是它所在函数(方法)的直接调用者对象。

再来看一段代码:
var where = 'in window';
function a(){
  this.where = 'in a ';
  this.b = function (){
    return this.c = function(){alert(this.where);};
  }
}
var o = new a();
//如果在这里调用o.c()会发生错误,因为o对象没有c属性。
var t = o.b();//执行这里的时候才在o对象上创建属性c
o.c();//alert "in a ",
t();//alert "in  window"
上面的运行结果是不是区分得很清楚了,谁调用了函数,this就是指向谁。

下面我们再看看this一些常用的用法:
1、纯粹的函数调用:
var val = 111;
function myFunc(){
    alert(this.val);//this指向window对象, 所以去掉this也是可以的
}
function otherFunc(){
    this.val = 222;//改写了val的值
    alert(this.val);
}
myFunc();//alert 111;
otherFunc();//alert 222;
myFunc();//alert 222;
像这种仅在函数中调用this,其实指的就是全局对象,在页面中也就是window对象了。

2、作为对象方法的调用:
var x=111;
var o={
    x:222,
    f:function(){
       alert(this.x);//这里的this指向的调用者o
    }
}
o.f();//alert 222;
alert(x);//alert 111;
3、作为构造函数调用:
var x=111;
function c(v){
    this.x = v;
    this.print = function(){
         alert(this.x);
    }
}
var o = new c(222);
o.print();//alert 222;
alert(x);//alert 111;
4、apply/call调用:
apply可以将调用者委托给另外一个对象(通过第一个参数传入,如果是空的话,会认为是全局对象)
call基本跟apply效果相同,只是apply第二个参数是用数组来传递参数列表,而call是直接用参数列表方式传递。
关于apply与call的详细解说可以参考csdn的一篇博文《apply方法详解》
var x  = 'x of the window';
var myObj = {
     x:'x Of myObj',
     print:function(){
         alert(this.x);
     }
}
var otherObj = {
    x:'x Of otherObj',
    print:function(){
        alert(this.x);
    }
}
myObj.print();//alert 'x Of myObj',未进行调用对象的委托
myObj.print.apply(otherObj);//alert 'x Of otherObj', 将调用对象委托给otherObj,所以this指向了otherObj.
myObj.print.apply();//alert 'x of the window',参数为空时,调用对象委托给全局对象window
再来看看一个现象:
function btnClick(){ alert(this.title); }
<input id="myBtn" type="button" onclick="btnClick()" value="click me" title="clicked the button" />
点击button,发现并没有弹出button的title属性。这里的this并不是input元素对象,而是window对象,如果你在window作用域下定义了一个变量title='window title',再去点击按钮发现弹出的是'window title',这也就证明了this指向的是window对象。其实onclick="btnClick()",相当于function onclick(event){btnClick();},而function onclick其实也是一个全局的function,上面的 btnClick方法也是全局的function,都可以视为window对象的两个属性。
再来做个实验:
$('body').append('<input id="myBtn" type="button" value="click me" title="clicked the button" />');
document.getElementById('myBtn').onclick = function(){
   alert(this.title);
}
点击myBtn时,弹出了‘clicked the button'。说明此时的this确实指向了myBtn这个元素对象,就因为绑定click事件处理函数的方式不一样,才会导致函数中this的指向不一样。更具体的解释可以参考jb51的一篇文章《javascript this用法小结》

利用间隔计数器进行数据递增的实现例子:
obj={
    step: 3,
    calc: function(callback){
        var t = setInterval(
            (function(v,f){ //匿名函数A
                var me = this;//this指向了obj
                return function(){ //匿名函数B,此函数将会每隔100ms被调用,由于闭包原理,它将一直维护对变量v的引用,于是可以对此变量进行累加。
                    v += me.step; //变量v和变量me都是闭包变量。
                    if(v>=100) { clearInterval(t), typeof(f)=='function' && f(v) }
                };
            }).call(this, 0, callback),
        100); //用call方法将obj对象应用到函数A中去,如果不这样做,在A中的this将指向window对象。因为在setTimeout,setInterval这些函数中,this指向的是window对象
    }
}
obj.calc( function(s){ //匿名函数C
			console.log(s);//out 102
		} );

正在加载评论...