当前位置:编程学习 > JAVA >>

玩转Javascript函数上下文绑定——Dojo hitch/partial详解

在dojo工具包中,dojo/_base/lang模块对Javascript原生方法进行了包装或增强,提供了不少相当有用的方法。本文将介绍Javascript中的函数对象(Function)的基础知识,以及如何使用dojo.hitch绑定函数的上下文,另外还将介绍如何使用dojo.partial为函数绑定特定参数等实用技术。

在讲解dojo.hitch和dojo.partial的用法之前,要先明白它们能解决什么问题。Javascript编程中最常听到的问题之一:this是什么?对面向对象编程来说,方法内部的this就是声明该方法的对象,非常简单!而对于Javascript,答案可不那么简单了。为求知其然并知其所以然,有必要了解Javascript中的函数上下文。

Javascript函数上下文


每当一个函数被调用时,Javascript会创建一个对应的上下文。上下文创建步骤如下:

创建argument对象;
创建函数的scope对象;
初始化函数的局部变量;
创建this属性;
其中this指向的是正在调用该函数的对象。理解这一点对于理解Javascript中的函数运行非常关键,因为Javascript中函数的上下文是在函数被调用的时候才确定的。


这里举一个例子:有一个object,这个object其中一个方法被当做多个HTML节点的点击事件的处理函数。下面是对应的代码。


[javascript]  var myObject = { 
    foo: "bar", 
    myHandler: function(evt){ 
        //  this is very contrived but will do.  
        alert("The value of 'foo' is " + this.foo); 
    } 
}; 
 
//  later on in the script:  
dojo.query(".myNodes").forEach(function(node){ 
    node.onclick = myObject.myHandler; 
}); 
        var myObject = {
            foo: "bar",
            myHandler: function(evt){
                //  this is very contrived but will do.
                alert("The value of 'foo' is " + this.foo);
            }
        };
 
        //  later on in the script:
        dojo.query(".myNodes").forEach(function(node){
            node.onclick = myObject.myHandler;
        });
请看对应的Demo(http://dojotoolkit.org/documentation/tutorials/1.7/hitch/demo/demo.html)

当这些class为“myNodes”的button被点击时,你可能会认为浏览器会弹出“The value of 'foo' is bar”的消息,然而由于上面的myObject.myHandler绑定了节点的点击事件,导致浏览器弹出了“The value of 'foo' is undefined”。这是因为myObject.myHandler被作为节点的上下文执行,并非被myObject自己执行。换句话说,Javascript解释器认为当前的this指向了被点击的节点而非myObject。

使用apply、call指定函数运行上下文


Javascript为函数对象提供了apply与call方法,用于切换函数的运行时上下文。两种方法都可以通过传入运行时上下文,从而显式地指定this属性的引用。举例来说,我们希望上例中的节点被点击时,触发的myObject.myHandler的上下文为myObject。这里使用call方法为例:


[javascript] dojo.query(".myNodes").forEach(function(node){ 
    node.onclick = function(evt){ 
        return myObject.myHandler.call(myObject, evt); 
    }; 
}); 
dojo.query(".myNodes").forEach(function(node){
    node.onclick = function(evt){
        return myObject.myHandler.call(myObject, evt);
    };
});


请看对应的Demo(http://dojotoolkit.org/documentation/tutorials/1.7/hitch/demo/call.html)

理解了Javascript函数的上下文基础后,来看看dojo如何使用dojo.hitch来简化这一过程。


使用dojo.hitch绑定函数运行时上下文

Dojo.hitch是dojo提供的一个用来简化函数运行时上下文绑定的函数。简单来说dojo.hitch创建了一个绑定了上下文的新函数,用户可以不用担心心运行时的上下文变化会对函数产生影响。使用dojo.hitch也十分简单:


[javascript] var foo = "bar" 
var myFunction = function(){ 
    return this.foo; 
}; 
var myObject = { foo: "baz" }; 
// later on in your application  
var boundFunction = dojo.hitch(myObject, myFunction); 
// the first value will be "bar", the second will be "baz";  
// the third will still be "bar".  
myFunction();       // "bar"  
boundFunction();    // "baz"  
myFunction();       // "bar" 
        var foo = "bar"
        var myFunction = function(){
            return this.foo;
        };
        var myObject = { foo: "baz" };
        // later on in your application
        var boundFunction = dojo.hitch(myObject, myFunction);
        // the first value will be "bar", the second will be "baz";
        // the third will still be "bar".
        myFunction();       // "bar"
        boundFunction();    // "baz"
        myFunction();       // "bar"


对应Demo(http://dojotoolkit.org/documentation/tutorials/1.7/hitch/demo/hitch.html)

可以看到,无论外部运行时上下文如何变化,dojo.hitch保证函数myFunction的上下文对象始终是myObject。

arguments对象

还记得之前Javascript被调用时创建上下文的步骤吗?首先创建的就是arguments对象,arguments对象是一个函数的参数数组,以参数的传入顺序排列该数组内元素。

当函数定义完成后,其函数签名就被固定下来。我们就不能增加或者删除非匿名的函数参数。有时候这限制了函数调用的灵活性,我们不得不重写新的函数来应付参数列表的变更,而dojo.partial方法打破了这个限制。


使用dojo.partial控制参数列表

首先看下面的例子(取自dojo/data模块),参数列表中有4个参数:

[javascript] var putValue = function(store, item, attr, value){ 
    return store.setValue(item, attr, value); 

var putValue = function(store, item, attr, value){
    return store.setValue(item, attr, value);
}
然而后来在应用需要与putValue有相似的功能但参数列表不同的函数,如下所示:


[javascript] //已声明的myStore对象  
var myStore = new dojo.data.ItemWriteStore({…}); 
someObject.setValueHandler = function(item, attr, value){ 
    myStore.setValue(item, attr, value); 
}; 
//已声明的myStore对象
var myStore = new dojo.data.ItemWriteStore({…});
someObject.setValueHandler = function(item, attr, value){
    myStore.setValue(item, attr, value);
};
doj

补充:web前端 , JavaScript ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,