理解JavaScript中this的指向详解

this的定义和理解:

this是JavaScript语言的一个关键字,它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内使用。

1、this和执行环境对象有关,和函数的声明无关。

   var name="Tom";
   var Bob={
      name:'Bob',
      show:function(){
         console.log(this.name);
      }
   };
   var show=Bob.show;   //等同于var show=function(){console.log(this.name);}
   show();   //输出的是Tom,全局对象调用show()函数
   window.Bob.show();   //输出是 Bob ,函数执行对象是Bob

   var someone={
      name:"盖伦",
      say:function(){console.log(this.name);}
   };
   var otherone={
      name:"杰克",
      speak:someone.say  //等同于声明函数speak:function(){console.log(this.name);}
   };
   otherone.speak();  //输出 杰克 ,函数被执行时this指向调用的对象otherone

上述代码解析:函数执行时,this指向的是函数运行时所在的当前环境对象。注意this和执行环境有关,和函数的声明无关。。也可以理解为this指向的是调用它的对象!

2、函数没有明确的执行对象时,this指向全局对象window。

   var a=11;
   function test1(){
      var person="zhangsan";
      console.log(this);      //输出全局对象window
      console.log(this.person);   //undefined
      console.log(this.a);    // 11
   }
   test1();   //没有明确函数执行对象时,this指向window全局对象
   window.test1(); //作用同上

   var name="Jack";
   var Rose={
      name:'rose',
      showName:function(){console.log(this.name);}
   };
   var Jane={
      name:'Jane',
      showName:function(){
         var fun=Rose.showName;  //等同于var fun=function(){console.log(this.name);}
         fun();  //在Jane.showName声明时执行了,没有明确的执行对象,this指向全局对象window
      }
   };
   Jane.showName();

   var obj = {
     a:10,
     b:{
        a:12,
        fn:function(){
            console.log(this.a); //undefined
            console.log(this); //window
        }
     }
   }
   var j = obj.b.fn;  //等同于 j=function(){console.log(this.a);console.log(this);}   
   j();  //所以this指向window, this.a是undefined

上述代码解析:没有明确的执行对象时,this指向全局对象window。浏览器中window是js中的全局对象,创建的对象和声明的函数实际是在给window添加属性;

3、定时器setTimeout 、setInterval 和匿名函数执行时的当前对象是全局对象window,定时器也可以理解为延迟执行的匿名函数

   var name="Jack";
   var nameObj={
      name:'rose',
      showName:function(){
         console.log(this.name);
      },
      waitShowName:function(){
         setTimeout(this.showName,5000);  //等同于延迟执行function(){...}(this.showName)的匿名函数
      }
   };
   nameObj.waitShowName();  //输出 Jack ,定时器和匿名函数执行的当前对象是window全局对象

   (function(val){
      if(val>10){
         console.log(this);  //输出window
      }
   })(55);

如何使定时器中的执行对象不是window对象,可以通过var that=this; 的形式保存定时器所在函数的对象,定时器中匿名函数使用that获取定时器所在的对象

var name = "Bob";  
var nameObj ={  
    name : "Tom",  
    showName : function(){  
        alert(this.name);  
    },  
    waitShowName : function(){
        var that = this;         //保存调用waitShowName()函数时的对象到that
        //定时器使用时,使用that也就是定时器所在对象nameObj,而不是window
        setTimeout(function(){
            that.showName();
        }, 1000);
    }
}; 
 
 nameObj.waitShowName();  //Tom

4、构造函数使用new关键词创建对象后,构造函数中的this指向该构造函数创建出来的新对象

   function Person(val){
      this.name=val
   }
   Person.prototype.show=function(){console.log(this.name);};
   var zhangsan=new Person("zhangsan"); //new关键词会根据构造函数创建一个新对象,this指向新对象
   zhangsan.show();

如果构造函数中使用return 返回一个对象,new 关键词创建的新对象会被return返回的对象替换,return返回的是非对象时this指向new创建的新对象,如下

function fn(){  
    this.name = 'Tom';  
    return {
       name:'xiaohong',
       showName:function(){
          console.log(this.name);
       }
    };  
}
var a = new fn;  
a.showName(); //输出 xiaohong

function fn(){  
    this.name = 'Tom';  
    return false;  //return 返回非对象
}
var a = new fn;  
console.log(a.name);  //输出 Tom

5、eval() 函数 和 new Function() 使用字符串作为执行的代码体

eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行如果参数是一个表达式,eval() 函数将执行表达式。如果参数是Javascript语句,eval()将执行 Javascript 语句。

   var a=eval('2+8');  //eval函数使用string作为参数,可以计算表达式或者执行js语句
   var b=eval('console.log("这是使用eval函数直接执行js语句获取的结果");');
   console.log(a);

类似 eval()函数,new Function() 可以将字符串当做代码(函数体)来执行。最后一个string参数做函数体,其他参数做该函数的参数

   //Function 这个构造函数可以用来创建函数对象

   //一个参数都不传的时候,创建了一个fn0的函数
   var fn0=new Function();
   console.log(typeof fn0);  //function

   //这里是创建了一个fn1的函数,只传一个参数string时,函数体就是传入的字符串形式的js语句
   var fn1=new Function("console.log('666666');");  
   fn1();  //输出 666666

   //传入多个参数的时候,最后一个参数作为函数体,前面的参数都作为该函数的参数
   var fn2=new Function("a","b","return a + b;"); 
   console.log(fn2(10,90));   //输出100

7、call() 和applay() 方法可以改变this指向。这里不细说,

后续会有一篇call、applay、bind改变this指向的文章详细分析,这里简单提一下

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

var other = {
    name: "Tom"
};    

someone.showName.apply();    //window
someone.showName.apply(other);    //Tom ,applay方法使得this指向为other对象

apply和call方法都用于改变函数执行时的当前对象,当无参数时,当前对象为window,有参数时当前对象为该参数。于是这个例子Bob成功偷走了Tom的名字;

参考网址:http://www.cnblogs.com/justany/archive/2012/11/01/the_keyword_this_in_javascript.html

猜你喜欢

转载自blog.csdn.net/zhouzuoluo/article/details/84966965
今日推荐