函数调用的四种模式
- 方法调用模式
- 函数调用模式
- 构造器调用模式
- Apply调用模式
方法调用模式
函数在作为一个对象的属性被调用的时候就属于方法调用模式。这个时候this是指向调用这个函数的对象的。
var myObject = {
value: 0,
increnment: function(){
this.value += 1;
}
}
myObject.increnment();
console.log(myObject.value); //=>1
上述例子中this.value
就相当于myObject.value
。
函数调用模式
当一个函数直接调用时就是函数调用模式。这时候this指向的是全局对象。
var value = 1;
function increnment(){
this.value += 1;
}
var myObject = {
value: 0,
callIncrement: function(){
increnment()
}
}
myObject.callIncrement();
console.log(value); //=>2
console.log(myObject.value); //=>0
这时候执行到increment
方法时,因为this指向的是全局对象,所以作增量的是全局的value
而不是myObject.value
。
这里规范说明下:根据ECMAScript3和非严格的ECMAScript5对函数调用的规定,调用上下文(this的值)是全局对象,然而,在严格模式下,调用上下文则是undefined。[摘自JavaScript权威指南(第六版)8.2.1 函数调用]
构造器调用模式
通过new
关键字调用的函数,属于构造器调用模式,这时this
指向的是这个新对象。
var o = {
value : 0,
ConstructorFunction: function(value){
this.value = value;
return this.value;
}
}
var b = new o.ConstructorFunction(2);
console.log(o.value); //=>0
console.log(b.value); //=>2
注意这里使用了new
关键字,因此这个时候this
指向的不再是方法调用模式下的调用对象,而是构造器返回的对象。所以这里的this.value = value
相当于b.value = value
。
同样规范的说明:然而如果构造函数使用return语句显示的返回一个对象,那么调用表达式的值就是这个对象。如果构造函数使用return语句但没有返回值,或者返回一个原始值,那么将忽略返回值,同时使用这个新对象作为调用结果。[摘自JavaScript权威指南(第六版)8.2.3 构造函数调用]
也就是说构造函数默认没有返回值时返回新对象,如果有使用return
返回值,则遵守如上约定。
Apply调用模式
因为函数本身也是对象,所以函数也可以拥有方法。在使用Apply方法调用函数时,this指向的是传递给apply方法中的第一个参数。
var obj = {
value: 0,
add: function(value){
this.value += value;
}
}
var myObj = { value: 1 };
function getValue(value){
this.value += value;
}
obj.add.apply(myObj,[3]);
console.log(obj.value); //=>0
console.log(myObj.value); //=>4
这里apply
方法第一个参数为this指向对象,第二个参数为调用函数的参数(通过数组方式传递)。因为apply
方法使this指向了myObj
,所以this.value+=value
相当于myObject.value+=value
。
说明
例子代码修改自《JavaScript语言精髓》26-30页。