您的位置:首页 > Web前端 > JavaScript

javascript中四种函数调用模式及对this的不同绑定

2010-06-10 16:40 791 查看

javascript中四种函数调用模式及对this的不同绑定

2009-10-31 19:41:20 技术 | 评论(0) | 浏览(314)

咱们的blog没有代码高亮的功能,觉得在这里看不清的同学请移步我自己的blog:http://blog.saymoon.com/2009/10/difference-from-this-in-invocation-for-function-by-four-ways/

撰写此文源于最近在看Douglas Crockford的'javascript :The Good Parts'中文译本《Javascript语言精粹》时,发现一些自己不知道或者没有一下子理解的东西,拿出来细细研究并记录一下。

函数被作为很重要的一部分在书中做了详细的介绍和举例。感觉函数的四种调用方式和在不同调用方式上'this'绑定的不同是个重点也是难点。欢迎大家一起研究。

方法调用模式:

调用形式:通过'.'点表达式或[subscript]下标表达式调用一个对象中的方法。
this绑定:this被绑定到被调用方法所属的对象上。
例子:

[js]
//  创建 myObject 对象。它有一个 value 属性和一个 increment 方法。
//  increment 方法接收一个可选参数。如果参数不是数字,那么默认使用数字1。

var g = 'global';

var myObject = {
value: 0,
increment: function (inc) {
document.writeln(this.g);
this.value += typeof inc === 'number' ? inc : 1;    //  在方法被调用时this被绑定为myObject对象。
}
};

document.writeln(this.g);     //  global
//  打印出全局变量g的值,说明this被绑定在全局对象上。
myObject.increment();    //  在这里increment方法才被调用,this才被绑定到myObject对象,这是特有“超级”迟绑定(very late binding)。
//  这时打印出的this.g为undefined,因为myObject中没有g这个属性,可以看出这时this被绑定到了myObject对象上。

document.writeln(myObject.value);    //  1
document.writeln(this.g);     //  global
//  打印出全局变量g的值,函数调用结束后,this又被从myObject对象上绑定回全局对象上。

myObject.increment(2);
document.writeln(myObject.value);    //  3
[/js]

函数调用模式:

调用形式:当一个函数并非一个对象的属性时,它被当作一个函数来调用。
this绑定:this被绑定到全局对象上。
例子:

执行下面的代码会发现,输出的结果是全局对象中g的值,与我们预期的结果不同,this被错误地绑定到全局对象上,这是JavaScript语言设计上的一个错误。

[js]
var g = 'global';

var o = function () {
var g = 'self';
document.writeln(this.g);    //  global    this被错误地绑定到全局对象。
}();
[/js]

如果设计正确的话,当内部函数被调用时,this 应该绑定到外部函数的 this 变量。
解决该错误的方法:在函数中定义一个变量并给它赋值为 this,那么内部函数就可以通过那个变量访问到被绑定到外部函数的正确 this。按照约定,我们给那个变量命名为 that。

[js]
var add = function (a, b) {
return a + b;
};

//  给 myObject 增加一个 double 方法。

myObject.double = function () {
var that = this;    //  解决方法

var helper = function () {
that.value = add(that.value, that.value);    //  这里的 that 被绑定到外部函数 myObject.double上
};

helper();    //  以函数的形式调用 helper
};

myObject.double();
document.writeln(myObject.value);    //  6
[/js]

构造器调用模式:

调用形式:在函数名前加 new 来调用。
this绑定:将创建一个隐藏连接到该函数的 prototype 成员的新对象,同时 this 将会被绑定到这个新对象上。
例子:

[js]
//  创建一个名为 Quo 的构造器函数。它构造一个带有 status 属性的对象。

var Quo = function (string) {
this.status = string;
};

//  给 Quo 的所有实例提供一个名为 get_status 的公共方法

Quo.prototype.get_status = function () {
return this.status;
};
[/js]

注意:在JavaScript中如果用 new 方式调用一个函数,如果函数没有返回一个对象,则返回 this。
下面在用 new 调用 Quo 这个构造函数时,因为 Quo 函数没有返回值,所以默认返回 this gei myQuo。

[js]
//  构造一个 Quo 实例

var myQuo = new Quo("confused");    //  myQuo 的值被赋予了 this,而此时的 this 是 Quo 的 prototype 成员。
document.writeln(myQuo.get_status());    //  confused    this.status 即 Quo.prototype.status 在调用 new 构造 Quo 时即被赋予了 confused。
document.writeln(myQuo.status);    //  confused
[/js]

如果调用构造器函数时前面没有加 new,将会发生错误:

[js]
var myQuo = Quo("confused");
document.writeln(myQuo);    //  undefined    可见,没有用 new 调用构造器函数,它将不会有任何返回值给 myQuo。
[/js]

Apply/Call调用模式:

调用形式:通过apply/call方法调用函数,其中第一个参数为我们指定的 this 的值。
this绑定:允许我们选择 this 的值。
例子:

[js]
//  构造一个包含两个数字的数组,通过apply方法调用前面的add函数,将数组中的数字相加

var array = [3, 4];
var sum = add.apply(null, array);    //  sum的值为7。add()中没有使用到 this 所以参数给其设为 null 即可。
[/js]

例子:

[js]
//  构造一个包含 status 成员的对象,通过 apply 方法调用前面的 Quo对象的get_status 方法返回 status。

var  statusObject = {
status : 'A-OK'
};

var status = Quo.prototype.get_status.apply(statusObject);    //  status 值为'A-OK'  在通过 apply 调用 Quo 的 get_status 方法时将 statusObject 对象绑定给了 this ,所以 get_status 方法返回的结果是 statusObject 的 status 属性。
[/js]

先总结这么多,有不清楚的地方大家提出来,俺再补充。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: