This的定义:

它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。

this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象,

这说明this关键字只与函数的执行环境有关,而与声明环境没有关系。下面通过例子来讲解。

例子1:

function a(){

    var user = "哈哈哈";

    console.log(this.user); //undefined

console.log(this); //Window

}

a();

 

既然this的最终指向的是那个调用它的对象,a()的执行就相当于window.a(),所以this指向window.

例子2:

var o = {

    user:"哈哈哈",

    fn:function(){

        console.log(this.user);  //哈哈哈    

}

}

o.fn();

 

这里的this指向的是对象o,因为你调用这个fn是通过o.fn()执行的,那自然指向就是对象o,这里再次强调一点,this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁。

例子3:

var o = {

    a:’哈哈哈’,

    b:{

        a:’呵呵呵’,

        fn:function(){

            console.log(this.a); //呵呵呵       

}

    }

}

o.b.fn();

 

如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象(不管有没有this要的东西,没有就输出undefined)。

例子4:

var o = {

    a:’哈哈哈’,

    b:{

        a:’呵呵呵’,

        fn:function(){

            console.log(this.a); //undefined

            console.log(this); //window        

}

    }

}

var j = o.b.fn;

j();

 

this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的,例子4中虽然函数fn是被对象b所引用,但是在将fn赋值给变量j的时候并没有执行所以最终指向的是window,这和例子3是不一样的,例子3是直接执行了fn。

例子5:

var id = 'windowId';

document.getElementById('myDiv').onclick = function() {

   console.log(this.id); //输出myDiv

   function fn(){

      console.log(this.id); //输出windowId

    };

    fn(); //普通函数调用

};

 

这里补充下:不管函数处于什么样的执行环境,只要是当普通函数调用,this就指向windows.

例子6:

var a=function(){

      console.log(this)//window

     }

     var o={

      name:'小白菜',

      b:function(fn){

         console.log(this);//{name:'小白菜',b:f(fn)}

         fn()

         a();

      }

     }

     o.b(function(){

      console.log(this)//window

     })

 

这个例子是我之前的面试题目,也是因为它而让我想写这篇文章。我想大家看到这里大概明白b函数里面的this,就是指向它的执行环境o。迷糊的估计是fn()和a()的输出。其实简单理解就像例5我所说的,不管处于什么样的环境下,只要当普通函数调用就指向window。硬要说个理由,就像开头所说的:this的最终指向的是那个调用它的对象。本例子fn()=window.fn()。

补充1:

1、

function fn()  

{  

    this.name = '哈哈哈';  

    return {};  

}

var a = new fn();  

console.log(a.name ); //undefined

2、

function fn()  

{  

     this.name = '哈哈哈';  

    return function(){};

}

var a = new fn();  

console.log(a.name ); //undefined

3、

function fn()  

{  

    this.name = '哈哈哈';  

    return 1;

}

var a = new fn();  

console.log(a.name ); //哈哈哈

4、

function fn()  

{  

     this.name = '哈哈哈';  

    return undefined;

}

var a = new fn();  

console.log(a.name ); //哈哈哈

5、

function fn()  

{  

    this.name = '哈哈哈';  

    return null;

}var a = new fn;  

console.log(a.name ); //哈哈哈

 

如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊。

补充2:

this一般指向的是当前被调用者,但也可以通过其它方式来改变它的指向,为什么要改变向上下文呢?主要是为了实现一种情况,当一个对象没有某个方法的时候,而且另外一个对象却有这个方法,这个时候就可以通过改变上下文来使用自己没有的方法了。

如下面的例子:

var obj1 = {
    name: '111'
}
var obj2 = {
    name: '222'
}
window.name = 'window';
var getName= function(a,b) {
    alert(this.name);
    alert(a);
    alert(b);
}

getName();//window,undefined,undefined;

getName.call(obj1,'a','b');//111,a,b

getName.apply(obj2,['a','b']);//222,a,b

 

obj1没有showName()方法,obj2有,这个时候可以这个样子使用,var temp=obj1.prototype.call(obj2);这样就可以用obj2的方法了。

那什么时候用call什么时候用apply?

当参数个数是固定不变的时候可以用call,当参数个数不确定可以用apply,把要传递的参数push到一个数组里面然后传递给函数,不清楚call和apply可以猛戳百度。