JavaScript中this出现的场景主要分为如下四类:
1、通过函数名直接调用,this指向window对象。
2、通告对象.函数名调用,this指向该对象(函数作为数组的一个元素,通过数组下标调用的:this指向这个数组)。
3、使用new关键字创建对象,this指向新创建的对象。
4、通告apply、call、bind改变this的指向。
一、通过函数名称直接调用:
function GetName(){
this.name ="robbin";
console.log(this.name);
}
GetName();//this指向window对象。
//为了说明this指向全局window对象,我们修改一下
var name = "sandy";
function GetName() {
console.log(this.name);
}
GetName();
function GetName() {
this.name="robbin";
}
GetName();
console.log(name);
二、函数作为对象的方法调用,此时this指向这个上级对象或者说代用对象。
function run() {
alert(this.name+"开始跑");
}
var person = {
name:"robbin"
};
person.run = run;
person.run();
三、通过new关键字创建对象,this指向新创建的对象,
function Person(){
this.name = "robbin";
}
var person = new Person();
alert(person.name);
//改变一下
var name = "sandy";
function Person(){
this.name="robbin";
}
var person = new Person();
alert(name);
四、通过apply、call、bind改变this
this本身是不可变的,但是 JavaScript中提供了call/apply/bind三个函数来在函数调用时设置this的值;apply()是函数对象的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象。因此,this指的就是这第一个参数。
var x = 0;
function test(){
alert(this.x);
}
var o={};
o.x = 1;
o.m = test;
o.m.apply(); //0
apply()的参数为空时,默认调用全局对象。因此,这时的运行结果为0,证明this指的是全局对象。
如果把最后一行代码修改为
o.m.apply(o); //1
运行结果就变成了1,证明了这时this代表的是对象o。
另外
DOM event handler
当一个函数被当作event handler的时候,this会被设置为触发事件的页面元素(element)。
var body = document.getElementsByTagName("body")[0];
body.addEventListener("click", function(){
console.log(this);
});
// <body>…</body>
In-line event handler
当代码通过in-line handler执行的时候,this同样指向拥有该handler的页面元素。
看下面的代码:
document.write('<button onclick="console.log(this)">Show this</button>');
// <button onclick="console.log(this)">Show this</button>
document.write('<button onclick="(function(){console.log(this);})()">Show this</button>');
// window
在第一行代码中,正如上面in-line handler所描述的,this将指向”button”这个element。但是,对于第二行代码中的匿名函数,是一个上下文无关(context-less)的函数,所以this会被默认的设置为window。
前面我们已经介绍过了bind函数,所以,通过下面的修改就能改变上面例子中第二行代码的行为:
document.write('<button onclick="((function(){console.log(this);}).bind(this))()">Show this</button>');
// <button onclick="((function(){console.log(this);}).bind(this))()">Show this</button>
保存this
在JavaScript代码中,同一个上下文中可能会出现多个this,为了使用外层的this,就需要对this进行暂存了。
看下面的例子,根据前面的介绍,在body元素的click handler中,this肯定是指向body这个元素,所以为了使用”greeting”这个方法,就是要对指向bar对象的this进行暂存,这里用了一个self变量。
有了self,我们就可以在click handler中使用bar对象的”greeting”方法了。
当阅读一些JavaScript库代码的时候,如果遇到类似self,me,that的时候,他们可能就是对this的暂存。
var bar = {
name: "bar",
body: document.getElementsByTagName("body")[0],
greeting: function(){
console.log("Hi there, I'm " + this + ":" + this.name);
},
anotherMethod: function () {
var self = this;
this.body.addEventListener("click", function(){
self.greeting();
});
}
};
bar.anotherMethod();
// Hi there, I'm [object Object]:bar
同样,对于上面的例子,也可以使用bind来设置this达到相同的效果。
var bar = {
name: "bar",
body: document.getElementsByTagName("body")[0],
greeting: function(){
console.log("Hi there, I'm " + this + ":" + this.name);
},
anotherMethod: function () {
this.body.addEventListener("click", (function(){
this.greeting();
}).bind(this));
}
};
bar.anotherMethod();
// Hi there, I'm [object Object]:bar
总结
在函数调用中,this是由激活上下文代码的调用者(caller)来提供的,即调用函数的父上下文(parent context ),也就是说this取决于调用函数的方式,指向调用时所在函数所绑定的对象。
总之一句话,this指向谁,不取决于在什么地方定义,而取决于在什么地方调用。谁调用,this就指向谁(上下文对象)。**
Example01
var context = "global";
var obj = {
context: "object",
method: function () {
console.log(this + ":" +this.context);
function f() {
var context = "function";
console.log(this + ":" +this.context);
};
f();
(function(){
var context = "function";
console.log(this + ":" +this.context);
})();
}
};
obj.method();
// [object Object]:object
// [object Window]:global
// [object Window]:global
对于有些没有上下文的函数,也就是说这些函数没有绑定到特定的对象上,那么这些上下文无关的函数将会被默认的绑定到global object上。
在这个例子中,函数f和匿名函数表达式在被调用的过程中并没有被关联到任何对象,所以他们的this都代表global object。
参考:
http://www.cnblogs.com/wilber2013/p/4909505.html
http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html