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可以猛戳百度。