JavaScript的this关键字

  和一些面向对象的语言一样,JavaScript也支持this关键字,顾名思义,this关键字指代本对象,在传统的面向对象语言中,this代表该方法所属的对象,或者该对象的指针。

  在JavaScript中没有类的概念,this方法的指代含义也有些许的变化,指代的是调用该方法的对象。

  还是以上次的程序作为例子:

 

var User = function() {
	this.username = 'username';
	this.password = 'password';
}

User.prototype.toString = function() {	
	return this.username + ':' + this.password;
};

  toString方法中就使用了this关键字来指代调用者本身,一般情况下,调用者和该方法的所属对象是一致的,这种情况下,就与其他语言没什么不同。不过,JavaScript中调用者和方法所属的对象并不一定是一致的,许多情况下与闭包特性结合,也能产生许多特殊的效果。下面是一个稍微复杂的例子。

 

var x = function() {
	this.show = function(msg, func, scope) {
		document.write(msg + " : " + this.value + '<br />');
		if (scope === undefined)
			scope = this;
		func.apply(scope, []);
		func.call(scope);
	}
};

var y = new x();
x.prototype.value = 4;

y.value = 5;

var z = new x();
z.value = 6;

var w = new x();
x.prototype.value = 7;

y.show('value is', function() {
	document.write('value in scope : ' + this.value + '<br />');
}, z);

y.show('value is', function() {
	document.write('value in scope : ' + this.value + '<br />');
}, x.prototype);

y.show('value is', function() {
	document.write('value in scope : ' + this.value + '<br />');
}, w);

  x构造函数定义了一个show方法,首先输出调用者的value值,然后如果scope没有传入,则定义为方法的调用者本身。

  随后出现了两个方法,分别为apply和call,这两个方法是所有function都具有的,作用是强制指定某对象作为该方法的调用者,两者除了调用格式略有不同,作用是相同的。这两句话以scope的身份调用了func。

  后面定义了y、z、w三个变量,都分别是x的实例,接着以y的身份调用了3次show方法,只有scope参数传入了不同的值。

  第一次传入了对象z,此时y作为show的调用者,而show中的参数匿名函数func的调用者却被设定为z,因此输出结果为:

 

value is : 5
value in scope : 6
value in scope : 6

  第二次传入x.prototype,原理如上面相同,show的func参数是由x.prototype调用的,因此输入结果为:

 

value is : 5
value in scope : 7
value in scope : 7

  第三次传入了对象w,原理也和上面相同,func的调用者是w,那么此时w的值是多少呢?我们在实例化w以后,我们修改了x.prototype.value的值,那么此时w的value应该是x.prototype.value修改前的值还是修改后的值呢?

  答案是修改后的值,结果是:

 

value is : 5
value in scope : 7
value in scope : 7

  因为w并没有显式定义value属性,因此w的value属性是位于其__proto__属性中,也就是x.prototype的引用,因此当x.prototype发生了改变,对于w也是会同时产生影响,具体关于prototype的原理和行为,请参考之前的其他文章。