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

JavaScript初学者的困惑——回调对象的方法

2010-03-30 23:59 211 查看
从一个例子说起
用JavaScript进行Web编程时,注册回调函数十分常见。最常见的例子是添加用户接口的事件响应(如button的onclick),还有 Ajax执行结束的回调。在实际情况中,我们常会遇到将对象的方法注册为回调函数的情况,这在JavaScript里实现并不是那么直接(straightforward),让我们先来看看以下一个例子:
function MyObject(val){
    this.val = val;
}
MyObject.prototype.alertVal = function(){
    alert(this.val);
}
var obj = new MyObject(8);
function register(callback){
    // some time later...
    callback();
}
这个例子包含以下一些信息:
我们有一个对象obj,它有一个属性val,以及一个方法alertVal
alertVal显示当前对象的val属性值,不同对象的val值可能不同(由构造函数的参数决定)
我们还有一个函数register,它不是obj对象的方法
register的功能是回调作为参数传给它的函数,它与onclick是类似的
那么,我们如何将obj的alertVal方法注册为register的回调函数呢?
直接但不正确的做法
很直接的,我们会想到将obj.alertVal作为参数,传递给register:
register(obj.alertVal);
但事情并不像我们所想的那样顺利,浏览器的提示信息不是obj的val值,而是undefined。让我们看看发生了什么:
首先我们将obj.alertVal作为参数,传递给register
此时在register函数中,callback === obj.alertVal
alertVal中的语句是alert(this.val);
而callback函数并没有在任何对象上调用,即不是someObj.callback的形式
所以此时alert(this.val)中的this不是obj对象,而是全局对象,具体到浏览器中是window对象
由于window对象没有val属性,故输出是undefined
那么,我们怎么才能正确的回调obj的alertVal方法呢?
利用Closure和匿名函数实现对象方法回调
Closure是JavaScript中一个十分重要的概念,限于篇幅这里不做深入的展开,有兴趣的朋友可以参考JavaScript Closures for Dummies 和JavaScript Closures 。
简单的说,当一个函数定义在另一个函数中时,就创建了一个Closure。一个Closure会记住它作用域内的变量绑定,这种绑定关系在函数调用中一直有效。这并不是很好理解,还是结合刚才的例子,这次我们用如下方法向register传递参数:
register(function(){obj.alertVal();});
看起来似乎没有很大区别不是么?但神奇的是,浏览器这次正确的输出了obj的val值,8。
简单的解释是,不同于 register(obj.alertVal),传递给register的回调函数并不是在register内部定义的,因此alertVal方法不会和 obj对象绑定,可以理解为传递了alertVal方法的函数体,即obj.alertVal()实际上被视作function() {alert(this.val)传递给了register函数。
而使用register(function(){obj.alertVal();})的形式,我们在register函数内定义了一个匿名函数,这个函数中的对象绑定关系会在register的作用域内始终体现。
做一个简单的对比和总结:
//register(obj.alertVal)时,传递给register的实际函数是:
function(){alert(this.val);}  //this根据当前上下文绑定,由于register不是对象方法,在浏览器中是与window对象绑定
//register(function(){obj.alertVal();})时,传递给register的实际函数是:
function(){obj.alertVal();}   //obj能够正确的绑定
更多的内容
以上我们的obj是一个全局对象,很多情况下,我们需要在对象的方法中进行回调函数的绑定,这只需要一点额外的步骤:
MyObject.prototype.registerMyAlertVal= function(){
    var obj = this;
    register(function(){obj.alertVal()});
}
可以在Javascript Method Callbacks 获取与本文相关的更多内容。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: