最近在学习js,学到了用js写类似java的类,很新奇。对其中this的用法有一些迷惑,所以上网找了下,理解在心里,整理到这里。
一、this的四种情况
1、纯js函数调用
var x = 0;
function test(){
this.x = 1;
}
test();
console.log(x);//-->1
这段代码输出结果为1。因为这种情况下this指代的是全局对象。
2、所在函数作为对象的方法调用
var x = 0;
function test(){
this.x = 1;
}
var a = {};
a.x = 2;
a.f = test;
a.f();
console.log(x);//-->0
console.log(a.x);//-->1
在这段代码中this指向的是拥有它的对象,也就是a,所以全局中的x的值没有变化,但是a中的属性x由2变为了1。
3、所在函数作为构造函数使用
var x = 0;
function Test(){
this.x = 1;
}
var t = new Test();
console.log(x);//-->0
console.log(t.x);//-->1
在这段代码中,函数Test被当做了构造函数。而Test中的this指向了用这个构造函数构造的对象。相当于给对象 t 新增了一个属性 x 并赋值为1。而全局对象中的 x 值没有改变。
4、所在的函数被apply调用
var x = 0;
function test(){
console.log(this.x);
}
var o = {};
o.m = test;
o.m.apply();//-->0
o,m.apply(o);//-->undefined
在上面的代码中用到了apply,apply函数的第一个参数是调用apply函数的方法的上下文(如果为空,默认是全局对象),所以第一个输出为全局对象中的x,第二个输出为o.x,但是对象o中没有x属性,所以输出undefined。
二、一个小例子
console.log('---this && call-----');
var test = 111;
function _add()
{
this.test = 444;
console.log(this.test);
}
function _sub()
{
this.test = 222;
console.log(this.test);
}
_add();//-->444
_sub();//-->222
_add.call(_sub); //-->444
console.log(test); //-->222
console.log(_sub.test); //-->444
上面这段代码中用到了call,call第一个参数也是用来作为调用call的那个函数的上下文(个人觉得call与apply的区别就在于call除了第一个参数之外可以传任意个参数,而apply只能再传一个数组,所有想传的参数都要放在那个数组中)。
所以_add.call(_sub);中发生的事情是add中的this指向了函数_sub,即add中的this.test=444;相当于给函数_sub新增了个属性test,并赋值为4。所以_add.call(_sub)会输出444。而console.log(_sub.test);也会输出444。
接下来把这段代码改动一下,会有如下结果。
console.log('------- change && compare----------');
var testa = 111;
function _adda()
{
//this.test = 444;
console.log(this.testa);
}
function _suba()
{
this.testa = 222;
console.log(this.testa);
}
_adda(); //-->111,_add中this指向window
var da=new _suba(); //_sub中this指向da
console.log(testa);//-->111
_suba(); //-->222,_sub中的this继续指向window
console.log(testa); //执行_suba()的结果!!
_adda.call(_suba); //-->undefined
// _add中this指向_sub,_sub无test属性,所以undefined