dojo.hitch 原理
在使用dojo的时候,遇到dojo.hitch这个函数 ,官方文档说的很清楚,将函数和作用域绑定起来,这让我想起了call和apply这两个函数,call和apply用于改变一个方法的执行上下文,JS中之所以提供者两个方法,我个人认为是和JS的作用域有关的,
JavaScript中代码执行都是属于某一个作用域的,这也是我前面博客提到的,this 在JS中是变化的,并且this,指向当前的作用域,此外还应该提到另外一个特性闭包,我想闭包对JS的开发者来说应该再熟悉不过了,我们所使用的框架,甚至自己写的“类”,闭包屡见不鲜,而闭包也是和作作用域密切相关的。
比较特殊的是,在js中,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量! 其次,要理解javascript中的垃圾回收机制,在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。 了解这两个概念后,我们在看闭包。 “官方”给出的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
这句话通俗的来说就是:JavaScript中所有的function都是一个闭包。不过一般来说,嵌套的function所产生的闭包更为强大,也是大部分时候我们所谓的“闭包”。看下面这段解释闭包的经典代码:

function a() {
var i = 0;
function b() { alert(++i); }
return b;
}
var c = a();
c();

在这里,a被b引用了。而b又被c引用了。这是对象不会被gc回收。这就形成了所谓的闭包。也就是说,在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量。
好了,深入理解之。再引入一片概念(copy....)
函数的执行环境(execution context)、活动对象(call object)、作用域(scope)、作用域链(scope chain)。以函数a从定义到执行的过程为例阐述这几个概念。
- 当定义函数a的时候,js解释器会将函数a的作用域链(scope chain)设置为定义a时a所在的“环境”,如果a是一个全局函数,则scope chain中只有window对象。
- 当执行函数a的时候,a会进入相应的执行环境(excution context)。
- 在创建执行环境的过程中,首先会为a添加一个scope属性,即a的作用域,其值就为第1步中的scope chain。即a.scope=a的作用域链。
- 然后执行环境会创建一个活动对象(call object)。活动对象也是一个拥有属性的对象,但它不具有原型而且不能通过JavaScript代码直接访问。创建完活动对象后,把活动对象添加到a的作用域链的最顶端。此时a的作用域链包含了两个对象:a的活动对象和window对象。
- 下一步是在活动对象上添加一个arguments属性,它保存着调用函数a时所传递的参数。
- 最后把所有函数a的形参和内部的函数b的引用也添加到a的活动对象上。在这一步中,完成了函数b的的定义,因此如同第3步,函数b的作用域链被设置为b所被定义的环境,即a的作用域。
到此,整个函数a从定义到执行的步骤就完成了。此时a返回函数b的引用给c,又函数b的作用域链包含了对函数a的活动对象的引用,也就是说b可以访问到a中定义的所有变量和函数。函数b被c引用,函数b又依赖函数a,因此函数a在返回后不会被GC回收。
在理解原理之后,我们来看看引用场景。
1.保护了函数a的安全性。
2.在内存中维持一个变量。
3.通过保护变量的安全实现JS私有属性和私有方法。
二、dojo.hitch()
看完闭包后,再来说说,我写本文的目的。dojo.hitch(scope,method).
官方解释是:Dojo.hitch is a neat function. It returns a function that will execute a given function in a given scope. This function allows you to control how a function executes, particularly in asynchronous operations。
看以下代码:
var args = {
url: "foo",
load: this.dataLoaded
};
dojo.xhrGet(args);
这段代码执行会怎么样呢?会报错。说dataLoaded不是个方法,或找不到。为什么呢。从代码中可以看出参数args的load想调用外部一个dataLoaded的方法。但是this引用却指向了args。而args里面可没有dataLoaded。
如何解决呢?
var args = {
url: "foo",
load: dojo.hitch(this, "dataLoaded")
};
dojo.xhrGet(args);
用dojo.hitch来控制dataLoaded函数执行的作用域为this,这个问题也就迎刃而解了。
说到了hitch,我们就来看看它在dojo库里是怎么实现的?
在说原理之前,还是一样先引入两个javascript 的方法, Function.apply(obj,args) 和 Function.call(obj,[param1[,param2[,…[,paramN]]]])。
这两个函数所做的事情没有太多差别,差异在于他们传入的参数,一个是args任意参数,一个是数组的参数。
大致用法如下,obj1.method.call(obj2,argument1...),
call的作用就是把obj1的方法放到obj2上使用,后面的argument1..这些做为其他参数传入。也可以说是obj1能够劫持obj2的方法并继承obj2的属性。
继承?对,就是继承。我们可以这么做。

<script>
function Animal()
{
this.name = 'Animal'; this.sleep = function(who)
{
alert(who + " sleep!!");
}
}
function Dog(){
Animal.call(this); }
function test(){
var dog = new Dog();
dog.sleep("dog");
}
</script>

结果是 dog sleep!!。
Animal.call(this)就使得,用Animal对象代替Dog中的this对象,这样Dog也就继承了Animal中的所有属性和方法了。这就实现了javascript里的继承。

<script>
function Animal()
{
this.name = 'Animal';
this.eat = function()
{
alert(this.name + " eat!!!");
}
}
function Dog(){
this.name = 'Dog';
}
function test(){
var animal = new Animal();
var dog = new Dog();
animal.eat();
animal.eat.call(dog);
}
</script>

结果是Animal eat!!!! 和dog eat!!! 这就是常规的用法了。让方法执行在dog的作用域上。this.name就变成了dog。
嗯,很熟悉吧。其实dojo.hitch()也是这么做的。它用的是apply方法。在前面也提到了,apply和call只有参数的区别。
好了,以下就是dojo.hitch的源码,

dojo.hitch = function(/*Object*/scope, /*Function|String*/method /*,...*/){
if(arguments.length > 2){
return d._hitchArgs.apply(d, arguments); // Function
}
if(!method){
method = scope;
scope = null;
}
if(d.isString(method)){
scope = scope || d.global;
if(!scope[method]){ throw(['dojo.hitch: scope["', method, '"] is null (scope="', scope, '")'].join('')); }
return function(){ return scope[method].apply(scope, arguments || []); }; // Function
}
return !scope ? method : function(){ return method.apply(scope, arguments || []); }; // Function
};

细节不表,还是很简单吧,就是使用apply将对应的方法apply到scope上,并传入相应的参数。
现在在公司做javascript和dojo。从轻量级的jquery到重量级的dojo,深深地体会到dojo的强大。相信后面有很多文章会介绍dojo和javascript的一些高级特性。
dojo.hitch 原理的更多相关文章
- Dojo动画原理解析
dojo中动画部分分为两部分:dojo/_base/fx, dojo/fx.dojo/_base/fx部分是dojo动画的基石,里面有两个底层API:animateProperty.anim和两个常用 ...
- Dojo 学习笔记 之 Dojo hitch&partial
原文: http://dojotoolkit.org/documentation/tutorials/1.10/hitch/index.html 版本: Dojo 1.10 为了更好地使用JavaSc ...
- 深入了解 Dojo 的服务器推送技术
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...
- dojo事件
dojo.connect 和 dojo.disconnect /*建立连接*/ dojo.connect(/*Object|null*/ obj, /*String*/ event, /*Object ...
- dojo入门
1.引入dojo.js dojo的发行包里有4个子目录,要引入的文件是名叫"dojo"的子目录里的dojo.js. 假设你是这样的目录结构: project | +--dojo-l ...
- JS中事件代理与委托
在javasript中delegate这个词经常出现,看字面的意思,代理.委托.那么它究竟在什么样的情况下使用?它的原理又是什么?在各种框架中,也经常能看到delegate相关的接口.这些接口又有什么 ...
- Delegation事情委托或代理
在javasript中delegate这个词经常出现,看字面的意思,代理.委托.那么它究竟在什么样的情况下使用?它的原理又是什么?在各种框架中,也经常能看到delegate相关的接口.这些接口又有什么 ...
- JavaScript事件代理和委托
在javasript中,代理.委托经常出现. 那么它究竟在什么样的情况下使用?它的原理又是什么? 这里介绍一下javascript delegate的用法和原理,以及Dojo,jQuery等框架中de ...
- JS 事件代理
事件处理器:onclick.onmouseover.... 在传统的事件处理中,你需要为每一个元素添加或者是删除事件处理器.然而,事件处理器将有可能导致内存泄露或者是性能下降——你用得越多这种风险就越 ...
随机推荐
- python内置函数大全
一.数学运算类 abs(x) 求绝对值1.参数可以是整型,也可以是复数2.若参数是复数,则返回复数的模 complex([real[, imag]]) 创建一个复数 divmod(a, b) 分别取商 ...
- JavaScript高级程序设计(六):关键字 void 和 delete 使用
一.void 1.概述:JavaScript中void是一个操作符,该操作符指定要计算一个表达式但是不返回值. 2.语法:JavaScript void (express) 或则 JavaScri ...
- iOS 9 适配需要注意的问题
iOS 9 适配需要注意的问题 1`网络适配_改用更安全的HTTPS iOS9把所有的http请求都改为https了:iOS9系统发送的网络请求将统一使用TLS 1.2 SSL.采用TLS 1.2 协 ...
- [jquery]基础篇--this与$this区别
参考: http://www.cnblogs.com/hannover/p/4109779.html 1.JQuery this和$(this)的区别 相信很多刚接触JQuery的人,很多都会对$(t ...
- [MAXscript Tool]FFX_PalyBack v1.1 ShowReel
自己的写的一个简单的脚本方便实现大面积的烟,火,爆炸,云的效果.能实现静态动态的切换,还有快速的偏移FumeFX的缓存,支持随机缓存 具体看这个插件的ShowReel,结算的三套基础的火焰然后用此脚本 ...
- 【制作镜像Win*】系统安装
图形化安装系统,在询问“进行何种类型的安装?”时,选择“自定义(高级)” 下一步看不到硬盘,如图: 选择“加载驱动程序”,安装驱动. 将相应版本的netkvm.inf和viostor.inf装上. 继 ...
- How to: Change icon in Inno Setup
1. Change the installer executable icon or the icon showed in Start Menu folder Using SetupIconFile ...
- WIX: Hide installed program from the Add/Remove Programs window.
Reference article : How to hide an entry in the Add/Remove Programs applet? In Wix source files, set ...
- 信息收集->DNS分析->dnsdict6
如何获取域名的IPV4/IPV6地址之dnsdict6的使用 dnsdict6是一个用于获取网站信息的工具.dnsdict6可以扫描网站并显示有多少域或者子域,也可以扫描ipv6/ipv4地址.dns ...
- OpenJudge/Poj 1088 滑雪
1.链接地址: bailian.openjudge.cn/practice/1088 http://poj.org/problem?id=1088 2.题目: 总Time Limit: 1000ms ...