您的位置:首页 > Web前端 > JavaScript

JS篇——javascript中的this

2016-06-02 14:55 363 查看
  一直以来貌似都还没有更新js篇,本来是打算将css3和html5更新完之后再从头总结js,最后发现开始那些好像也没啥总结的,而且我这速度还不知道何时能把css3和html5总结完,所以就想到哪就更哪了,本来今天准备更新闭包,然后发现更新闭包之前,我最好先更新下js中的this关键字,所以这一篇更新js中的this关键字。

javascript中的this

在java中,this固定指向运行时的当前对象。但在javascript中,this的含义要多的多,它可以是全局对象、当前对象或者任意对象,完全取决于函数调用的方式。

this究竟指向哪里

一句话,javascript中的this指向的是执行时的当前对象,而不是声明时的当前对象。这句话什么意思,看下面例子。

var x=1;
var test= {
x: 2,
show : function(){
alert(this.x);
}
};
var obj = test.show;
obj();//1

上面这个例子最后弹出的是全局变量1,虽然this是在test.show里面声明的,但是执行的时候的对象却不是test,所以this不是指向的test对象,这是为啥呢,后面再说。

Javascript一共有四种调用模式:对象方法调用模式、纯函数调用模式、构造器调用模式以及apply调用模式。调用模式不同,对应的隐藏参数this值也会不同。

对象方法调用模式

函数作为对象的属性时,称为方法。此时函数(即方法)中的this对应是该对象。

var x=1;
var test= {
x: 2,
show : function(){
alert(this.x);
}
};
test.show();//2
弹出2,此刻运行的是test对象的show属性,所以this指向test对象,所以当前对象是test对象。

然而,还有另外一种情况的方法调用,就是“this究竟指向哪里”中的例子。

var x=1;
var test= {
x: 2,
show : function(){
alert(this.x);
}
};
var obj = test.show;
obj();//1
此时弹出的是1,此刻并不是调用了test这个对象的show属性,而是将test.show这个函数赋值给obj,又因为该函数是一个匿名函数,本身是没有对象的,所以show方法里的this就没有对象,没有对象就是window,window.x就是全局变量1。

谈到这里就顺便说一下setTimeout、setInterval和匿名函数中的“this”.

在浏览器中setTimeout、setInterval和匿名函数执行时的当前对象是全局对象window,浏览器中全局变量可以当成是window对象下的变量,例如:全局变量a,可以用window.a来引用。

var x=1;
var test= {
x: 2,
show : function(){
alert(this.x);
},
other:function(){
setTimeout(function(){
alert(this.x);
}, 1000);
}
};
test.other();//1
弹出1,这是因为setTimeout中的匿名函数运行时,匿名函数中的this指向window,所以window.x弹出1。setInterval与setTimeout类似。

怎样可以让上面例子弹出2呢?

var x=1;
var test= {
x: 2,
show : function(){
alert(this.x);
},
other:function(){
var that = this;
setTimeout(function(){
alert(that.x);
}, 1000);
}
};
test.other();//2

弹出2,这是因为在setTimeout中的匿名函数运行前,this指定的当前对象是test(这时运行的test对象的other属性),现将test对象赋值给that,setTimeout中的匿名函数运行后,改变的是this指定的对象,与that无关,that仍指定test对象。

这里再说一下setTimeout(函数名,延迟),setTimeout(匿名函数,延迟),setTimeout(字符串,延迟)这三的区别。以下面例子为例:

var x=1;
var test= {
x: 2,
show : function(){
alert(this.x);
}
};
setTimeout(函数名,延迟)(比如setTimeout(test.show(),1000))

test.show()是函数运行,这种传递方式真正传进去的是test.show()函数的返回值。如果是setInterval(test.show(),1000)这种方式只会执行test.show()一次,因为test.show()已经执行了,和setTimeout、setInterval其实没有关系。

setTimeout(匿名函数,延迟)(比如setTimeout(test.show,1000))

这个相当于一个延时执行,传入了一个匿名函数,此时this变量是全局变量window,但是注意,它是没有传入函数参数的,如果函数有参数的话,建议使用闭包或者使用setTimeout(字符串,延迟)

setTimeout(字符串,延迟)比如setTimeout("test.show()",1000))

这个也相当于一个延时执行,用字符串代码创建了一个新的函数,因此该函数没有明确的对象,所以this指向全局变量。

var x = 1;
var obj ={
x : 2,
show : function(){
alert(this.x);
},
other : function(){
var that = this;
setTimeout("that.show();", 1000);
}
};

obj.other();//报错
纯函数调用模式

这种很简单,此时this就代表全局对象,即window。

function show(){
this.x = 2;
alert(this.x);
}
show();//2
var x = 1;
function show(){
alert(this.x);
}
show();//1
var x = 1;
function show(){
this.x = 2;
}
show();
alert(this.x);//2
构造器调用模式

构造器,就是生成一个新对象,这时,这个this就指这个新对象。

var x=1;
function show(){
x=2;
alert(x);
alert(this.x);
var x;
alert(this.x);
alert(x);
}
show();
上面弹出的结果是2,1,1,2

这就是上面说的那种情况,纯函数调用模式,这里的this对象就是全局对象window.

var x=1;
function show(){
x=2;
alert(x);
alert(this.x);
var x;
alert(this.x);
alert(x);
}
var test = new show();
test();
上面弹出的是2,undefined,undefined,2

这里的this对象就是new新创建的对象,新创建的对象里面并没有定义this.a,所以this.a为undefined。

apply调用模式

apply()是函数对象的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象,因此,this指的就是这第一个参数。
call的用法和apply大致相同,只有一点区别,apply只接受两个参数,第一个参数和call相同,第二个参数必须是一个数组,数组中的元素对应的就是函数的形参。所以这里只主要讲一个apply。

var x=1;
function show(a){
this.x = this.x+a;
alert(this.x);
}
var obj = {
x:0
};
show.apply();//NaN,apply()的参数为空时,默认调用全局对象,所以this.x为1,但此时show函数的参数中没有定义a,因此a为undefined,所以结果为NaN
show.apply(obj,[3]);//3,此时this对象为obj对象,所以this.x为0。0+3等于3。
show.call(obj,4);//7,此时this对象是obj对象,但因为上一步,所以现在obj中的x为3,3+4等于7


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息