javascript中的this含义很丰富,它能够是全局对象,当前对象或者是随意对象,这都取决于函数的调用方式。函数有下面几种调用方式:作为对象方法调用、作为函数调用、作为构造函数调用、apply或call调用。
对象方法调用
作为对象方法调用的时候。this会被绑定到该对象。
var point = {
x : 0,
y : 0,
moveTo : function(x, y) {
this.x = this.x + x;
this.y = this.y + y;
}
}; point.moveTo(1, 1)//this 绑定到当前对象,即 point 对象
这里我想强调一点内容,就是this是在函数运行的时候去获取相应的值,而不是函数定义时。即使是对象方法调用,假设该方法的函数属性以函数名的形式传入别的作用域,也会改变this的指向。我举一个样例:
var a = {
aa : 0,
bb : 0,
fun : function(x,y){
this.aa = this.aa + x;
this.bb = this.bb + y;
}
};
var aa = 1;
var b = {
aa:0,
bb:0,
fun : function(){return this.aa;}
}
a.fun(3,2);
document.write(a.aa);//3,this指向对象本身
document.write(b.fun());//0,this指向对象本身
(function(aa){//注意传入的是函数。而不是函数运行的结果
var c = aa();
document.write(c);//1 , 因为fun在该处运行,导致this不再指向对象本身。而是这里的window
})(b.fun);
这样就明确了吧。这是一个easy混淆的地方。
函数调用
函数也能够直接被调用,这个时候this被绑定到了全局对象。
var x = 1;
function test(){
this.x = 0;
}
test();
alert(x); //0
但这样就会出现一些问题。就是在函数内部定义的函数。其this也会指向全局。而和我们希望的恰恰相反。代码例如以下:
var point = {
x : 0,
y : 0,
moveTo : function(x, y) {
// 内部函数
var moveX = function(x) {
this.x = x;//this 绑定到了全局
};
// 内部函数
var moveY = function(y) {
this.y = y;//this 绑定到了全局
}; moveX(x);
moveY(y);
}
};
point.moveTo(1, 1);
point.x; //==>0
point.y; //==>0
x; //==>1
y; //==>1
我们会发现不但我们希望的移动呢效果没有完毕,反而会多出两个全局变量。
那么怎样解决呢?仅仅要要进入函数中的函数时将this保存到一个变量中,再运用该变量就可以。代码例如以下:
var point = {
x : 0,
y : 0,
moveTo : function(x, y) {
var that = this;
// 内部函数
var moveX = function(x) {
that.x = x;
};
// 内部函数
var moveY = function(y) {
that.y = y;
}
moveX(x);
moveY(y);
}
};
point.moveTo(1, 1);
point.x; //==>1
point.y; //==>1
构造函数调用
在javascript中自己创建构造函数时能够利用this来指向新创建的对象上。
这样就能够避免函数中的this指向全局了。
var x = 2;
function test(){
this.x = 1;
}
var o = new test();
alert(x); //2
apply或call调用
这两个方法能够切换函数运行的上下文环境。也就是改变this绑定的对象。
apply和call比較类似,差别在于传入參数时一个要求是数组。一个要求是分开传入。所以我们以apply为例:
<pre name="code" class="html">var name = "window"; var someone = {
name: "Bob",
showName: function(){
alert(this.name);
}
}; var other = {
name: "Tom"
}; someone.showName(); //Bob
someone.showName.apply(); //window
someone.showName.apply(other); //Tom
能够看到,正常訪问对象中方法时,this指向对象。
使用了apply后,apply无參数时,this的当前对象是全局,apply有參数时,this的当前对象就是该參数。
箭头函数调用
这里须要补充一点内容。就是在下一代javascript标准ES6中的箭头函数的 this始终指向函数定义时的 this,而非运行时。我们通过一个样例来理解:
var o = {
x : 1,
func : function() { console.log(this.x) },
test : function() {
setTimeout(function() {
this.func();
}, 100);
}
}; o.test(); // TypeError : this.func is not a function
上面的代码会出现错误,由于this的指向从o变为了全局。我们须要改动上面的代码例如以下:
var o = {
x : 1,
func : function() { console.log(this.x) },
test : function() {
var _this = this;
setTimeout(function() {
_this.func();
}, 100);
}
}; o.test();
通过使用外部事先保存的this即可了。这里就能够利用到箭头函数了。我们刚才说过,箭头函数的 this始终指向函数定义时的 this,而非运行时。所以我们将上面的代码改动例如以下:
var o = {
x : 1,
func : function() { console.log(this.x) },
test : function() {
setTimeout(() => { this.func() }, 100);
}
}; o.test();
这回this就指向o了,我们还须要注意一点的就是这个this是不会改变指向对象的,我们知道call和apply能够改变this的指向,可是在箭头函数中是无效的。
var x = 1,
o = {
x : 10,
test : () => this.x
}; o.test(); // 1
o.test.call(o); // 依旧是1
这样就能够明确各种情况下this绑定对象的差别了。