js中的this是在运行时绑定的,所以this的含义十分丰富,它可以是全局对象,当前对象或任意对象 ,完全取决于函数的调用方式。函数的调用方式有几种:作为对象方法调用、作为函数调用、作为构造函数调用、和使用apply或call调用。
作为对象方法调用
在 JavaScript 中,函数也是对象,因此函数可以作为一个对象的属性,此时该函数被称为该对象的方法,在使用这种调用方式时,this 被自然绑定到该对象。
var point = {
x : 0,
y : 0,
moveTo : function(x,y){
this.x = x;
this.y = y;
}
};
point.moveTo(1,2);
console.log(point); // x:1 y:2
作为函数调用
函数直接调用,this绑定到全局对象。在浏览器中,window即为该全局对象。
function test(x){
// 'use strict';
this.x = x;
}
test(3);
console.log(x); // 3
函数被调用时,this绑定到全局对象,接下来执行赋值语句,相当于隐式声明了一个全局变量。 注意,这种调用方式下,非严格模式绑定到全局对象,严格模式将绑定到undefined(提示出错)。
在闭包函数中,情况比较特殊,需要特别注意:
var point = {
x:0,y:0,
moveTo : function(x,y){
var moveX = function(x){
this.x = x;
}
var moveY = function(y){
this.y = y;
}
moveX(x);
moveY(y);
}
};
point.moveTo(3,4);
console.log(point);
console.log(x+':'+y); // 3:4
这种情况下,怎么解决呢,解决方法如下:
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(3,4);
console.log(point);
console.log(x+':'+y);
因为函数当作函数调用时,this被绑定到全局对象,因此可以定义一个局部变量that,作为当前运行环境对象的引用。
作为构造函数调用
ES5中并没有类的概念,而是基于原型(prototype)的继承方式。js中构造函数很特殊,使用new即生成对象,不使用new则为普通函数一样。构造函数以大写字母开头。
function Point(x,y){
this.x = x;
this.y = y;
}
var point = new Point(3,4);
console.log(point);
call或apply调用
她们是函数对象的方法,允许切换函数执行的上下文环境,即this绑定的对象。
function Point(){
this.x = 0,
this.y = 0,
this.moveTo = function(x,y){
this.x = x;
this.y = y;
}
};
var point = new Point();
point.moveTo(2,2);
var point2 = {x:0,y:0};
point.moveTo.call(point2,5,6);
console.log(point); // x:2 y:2
console.log(point2); // x:5 y:6