JAVASCRIPT this关键字详解

来源:互联网 发布:数据光端机 编辑:程序博客网 时间:2024/05/02 00:11

this指向哪里?

一般而言,this指向函数执行时的当前对象。

In JavaScript, as in most object-oriented programming languages, this
is a special keyword that is used within methods to refer to the
object on which a method is being invoked.

——jQuery Fundamentals (Chapter 2), by Rebecca Murphey

值得注意的是:该关键字在javascript执行环境中,而非声明环境中。

什么意思呢,举例说明:
例1:

    var name = 'window';    var someone = {         name : 'tom',         showName : function(){             alert(this.name);        }    var other = {        name : 'Bob',        showName : someone.showName        }    other.showName(); //Bob
 结果显示Bob.  this关键字虽然声明在someone.showName,但运行时是在other.showName,所以this指向other对象。所以弹出的是Bob。

没有明确的当前对象时

在没有明确的运行时对象时,this指向全局对象(global),在浏览器环境中也就是window对象。
By default, this refers to the global object.

为什么说是全局对象(the global
object),因为非浏览器情况下(例如:nodejs)中全局变量并非window对象,而就是叫“全局变量”(the global
object)。

对与this到底指向谁,只要抓准这两点(一般而言,this指向函数执行时的当前对象,当没有明确的当前对象时,this指向全局对象)就可以慢慢弄明白!

例如对于全局变量引用的函数上有:
例2:

var name = 'window';var Tom = {        name : 'Tom',        showName : function(){            alert(this.name);        }    }   var method = Tom.showName;   //method全局变量method();  //window

在执行到var method = Tom.showName;这一句的时候,showName是对一个方法的引用(而没有执行),而把这个引用又赋值给了全局变量method。也就是说method指向了方法function(){
alert(this.name);
}
的引用,而method是一个全局变量,所以this指向window对象。
如果它

但是对于局部变量来说:
例3:

var name = 'window';var Tom = {        name : 'Tom',        showName : function(){            alert(this.name);        }    }   var Bob = {    name : 'Bob',    showName : function(){            var f = Tom.showName;            f();        }    }    Bob.showName();

在程序执行到Bob.showName();时,showName方法的this指向Bob对象没错,也就是说

function(){            var f = Tom.showName;            f();        }

方法的this指向Bob,如果在
var f = Tom.showName之前加上一句alert(this.name)

function(){            alert(this.name);  //Bob            var f = Tom.showName;            f();        }

则会弹出’Bob’。
但方法内部方法f的this并不是指向Bob,这里没有明确说明this的指向,所以f方法的this指向window,所以执行f()
结果为’window’

setTimeout、setInterval和匿名函数

在浏览器中setTimeout、setInterval和匿名函数执行时的当前对象是全局对象window,这条我们可以看成是上一条的一个特殊情况
例4:

var name = "Bob";  var nameObj ={      name : "Tom",      showName : function(){          alert(this.name);      },      waitShowName : function(){          setTimeout(this.showName, 1000);      }  };  nameObj.waitShowName();

在程序执行到nameObj.waitShowName();这一句时,waitShowName()的this指向nameObj对象,也就是

function(){          setTimeout(this.showName, 1000);      }  

里的this指向nameObj,所以this.showName才成立,如果这里没有this,而直接写showName则报错。但setTimeout实际调用的就是showName方法,方法体为{alert(this.name)},在调用它的时候没有指定this的指向,所以this指向window。所以最终结果为‘window’。

将代码改成匿名函数可能更好理解一些:
例5:

var name = "window";   var nameObj ={       name : "Tom",       showName : function(){           alert(this.name);       },       waitShowName : function(){           !function(__callback){            __callback();        }(this.showName);       }   };    nameObj.waitShowName();  

在调用nameObj.waitShowName时候,我们运行了一个匿名函数,将this.showName函数作为回调函数传递进这个匿名函数,在匿名函数运行时运行回调函数,因为匿名函数的this指向window,所以当在该匿名函数中运行回调函数时,回调函数的this也指向window。
由此看来
setTimeout、可以看做一个延迟执行的
function (_callback){
_callback();
}
setInterval同理。
如上例,如果一定需要在一秒钟之后显示nameObj 对象的name属性,可以做一些调整

 var name = "window";   var nameObj ={       name : "Tom",       showName : function(){           alert(this.name);       },       waitShowName : function(){           var that = this;         setTimeout(function(){         that.showName();        },1000);     }   };    nameObj.waitShowName();

这样与setTimeout的this指向window并不矛盾。setTimeout执行的具体方法是function(){ that.showName() };
that指向nameObj。并不是showName方法,所以showName方法的this指向就是它的调用者that,也就是nameObj对象。这里体现了最重要的一点:方法嵌套其实很有讲究,this并不能继承到子方法里去。

new关键字

new关键字后的构造函数中的this指向用该构造函数构造出来的新对象。

function Person(_name){    this.name = _name;}Person.prototype.showName = function(){        alert(this.name);    }var tom = new Person('Tom');tom.showName();  //Tom
0 0