最近在看道格拉斯的Javascript语言精粹,看到其中函数部分,总结一下Javascript中的this关键字。 道格拉斯总结函数的调用总共包含四种调用模式:方法调用模式(The Method Invocation Pattern)、函数调用模式( The Function Invocation Pattern)、构造函数调用模式(The Constructor Invocation Pattern)和Apply调用模式(The Apply Invocation Pattern)。
- 方法调用模式
定义:当一个函数被保存为对象的一个属性时,我们称它为一个方法。 当方法被调用时,this关键字指向该对象。通俗的讲,就是如果一个函数是通过.或者[]来调用时,它就是一个方法调用。 示例:
// Create myObject. It has a value and an increment
// method. The increment method takes an optional
// parameter. If the argument is not a number, then 1
// is used as the default.
var myObject = {
value: 0,
increment: function (inc) {
this.value += typeof inc === 'number' ? inc : 1;
}
};
myObject.increment( );
document.writeln(myObject.value); // 1
myObject.increment(2);
document.writeln(myObject.value); // 3
- 函数调用模式
定义:当一个函数并非一个对象的属性时,那么它就是被当作一个函数来调用的。 此时,this被绑定到全局变量。道格拉斯说这是语言设计上的一个错误,幸亏,这个错误也很容易解决。通过在函数申明一个self变量,将它指向this,在函数调用中使用self代替this就能解决这个问题。 示例:
// Augment myObject with a double method.
myObject.double = function ( ) {
var self = this; // Workaround.
var helper = function ( ) {
self.value = add(self.value, self.value);
};
helper( ); // Invoke helper as a function.
};
// Invoke double as a method.
myObject.double( );
console.log(myObject.value);
- 构造器调用模式
定义:如果一个函数前面带上new来调用,那么背地里将会创建一个连接到该函数prototype成员的新对象。 此时,this会绑定到那个新对象上。 示例:
// Create a constructor function called Quo.
// It makes an object with a status property.
var Quo = function (string) {
this.status = string;
};
// Give all instances of Quo a public method
// called get_status.
Quo.prototype.get_status = function ( ) {
return this.status;
};
// Make an instance of Quo.
var myQuo = new Quo("confused");
console.log(myQuo.get_status( )); // confused
- Apply调用模式
定义:apply方法让我们构建一个参数传递数组传递给调用函数。它允许我们选择this的值。 apply方法接收两个参数,第一个是要绑定到this的值,第2个就是参数的一个数组。 (call方法和apply方法相似,只是call方法中参数是按arg1,arg2,arg3的方式传入,而apply则是按[arg1,arg2,arg3]当成一个参数来传递) 示例:
// Make an array of 2 numbers and add them.
var array = [3, 4];
var sum = add.apply(null, array); // sum is 7
// Make an object with a status member.
var statusObject = {
status: 'A-OK'
};
// statusObject does not inherit from Quo.prototype,
// but we can invoke the get_status method on
// statusObject even though statusObject does not have
// a get_status method.
var status = Quo.prototype.get_status.apply(statusObject);
// status is 'A-OK'
参考文献:
- Douglas Crockford 《Javascript:The Good Parts》