Javascript的回调,闭包与dojo.hitch

如何用Javascript解析HTML? 问题的提出是我需要将另一个网页的某些内容解析出来并集成到当前正在处理的网页中。第一想法就是,使用dojo.xhrGet得到网页的内容,再使用某种Javascript Library来解析。我熟悉的dojo并没有这种库,查询了一下,jQuery也没有。后来发现jQuery的作者,鼎 阅读详情

事件驱动机制的重要元素就是回调函数。事件驱动的本质是当程序运行到等待某个资源加载时(比如I/O),并非由程序去轮询资源的状态,而是注册一个消息处理程序(回调函数),当资源可用时(即事件发生时),事件来调用这个消息处理程序以消费该资源。

消息处理程序通常要携带参数,否则,它们就只能访问全局变量,这显然是不可接受的方式。在C/C++程序中,回调函数的参数通常由一个类型为(void *)的指针传递。在C#中引入了仿函数的概念。仿函数即是把消息处理程序和它所运行所需要的上下文环境包装在一起成为一个对象,一起传递给消息派发机制,消息派发机制针对该对象调用它的处理函数,这样,使得回调过程也可以以易于理解的面向对象的处理方式进行。

那么,在Javascript和dojo中,如何实现普通的回调函数和仿函数功能?先来看一个简单的例子:

function foo(/*String*/name){
    console.log("hi, how're you?");
}

setTimeout(foo, 2000);

上述示例中,foo就是一个普通的回调函数。在Firebug中运行该程序,firebug控制台将在2秒钟以后打印出:how're you?

上面的示例程序有个小小的遗憾,setTimeout只接受两个参数,因些它不能将foo函数需要的name参数传递进去。这里似乎是仿函数的概念可以起作用的地方。如果我们可以将一个对象传递给setTimeout,而这个对象又能象函数一样调用,那么似乎问题就可以解决了。Javascript的世界里没有仿函数这个概念,取而代之的是外延更宽广的闭包概念:

 function foo(/*String*/name){
    console.log("hi " + name + ", how're you?");
 }

 var functor = function(name){
    return function(){
        foo(name);
    }
}('aaron');

setTimeout(functor , 500);

上述示例中'var functor =...'一行声明了一个闭包并立即执行它,从而我们得到了一个指向闭包的对象。有一点值得注意,代码第5行,"function()"中不可带有形式参数name,否则第6行foo(name)中的name无法取得正确的值。因为形式参数的值是在函数调用时赋予的。如果第5行写成这样:"return function(name)",显然这个形参是无法赋值的。

 

闭包能保存其生成时所处上下文的全信息,这些信息包括函数调用参数,本地参数。

再来考察一个复杂一点的例子,使用了dojo的API:

var args = {
  url: "foo",
  load: this.dataLoaded
}
dojo.xhrGet(args);

这段代码首先定义了dojo.xhrGet所需要的参数。xhrGet是dojo封装的XMLHttpRequest请求中的HTTP GET请求。它的参数中,url是要访问的资源的URL,'load'则是当该资源获取到本地后需要调用的回调函数。当定义变量var args时,显然this是等同于args对象的。问题是,dojo.xhrGet取回资源,再来调用this.dataLoaded函数时,此时的this是xhrGet运行环境下的'this',并非args变量本身。【关于this:当代码处于定层位置时,this指的是宿主对象,在浏览器中即为window对象。当代码处于字面量对象定义当中(如本例)时,'this'相当于该字面量对象】。上述示例中即使是使用args.dataLoaded也是不行的,因为在xhrGet的运行环境下,仍然有可能不在args的作用域范围内。

显然,这时应该使用闭包,将回调函数及其运行环境封装起来一起传递给dojo.xhrGet().当然可以使用前面生成闭包的技巧,但dojo提供了一个漂亮的方法:dojo.hitch

var args = {
  url: "foo",
  load: dojo.hitch(this, "dataLoaded")
}
dojo.xhrGet(args);

使用dojo.hitch来改写前面的例子:
var obj = {
    name : 'aaron',
    method: function(){
                console.log("hi " + this.name + ", how're you?");
            }
}

var functor = dojo.hitch(obj, "method");
setTimeout(functor , 500);

代码中以下几点需要注意:

dojo.hitch作用于对象,因此首先要将方法及其访问的上下文包装成一个对象。这在面向对象的编程方式中是很常见的。对于method方法的定义,同样要注意这里定义时,不能带形式参数。method要访问的数据只能通过成员变量来获取,其次,引用成员变量时,要加上'this'关键字。否则,console.log语句会在全局作用域中寻找name。

最后,调用dojo.hitch时,一定要写成示例那样,而不能写成dojo.hitch(obj, method)。如此一来dojo会在全局作用域中去寻找method方法,从而导致出错。

最后,我们来看看dojo是如何实现hitch方法的(dojo/_base/lang.js):

dojo.hitch = function(/*Object*/scope, /*Function|String*/method /*,...*/){
    //    summary:
    //        Returns a function that will only ever execute in the a given scope.
    //        This allows for easy use of object member functions
    //        in callbacks and other places in which the "this" keyword may
    //        otherwise not reference the expected scope.
    //        Any number of default positional arguments may be passed as parameters
    //        beyond "method".
    //        Each of these values will be used to "placehold" (similar to curry)
    //        for the hitched function.
    //    scope:
    //        The scope to use when method executes. If method is a string,
    //        scope is also the object containing method.
    //    method:
    //        A function to be hitched to scope, or the name of the method in
    //        scope to be hitched.
    //    example:
    //    |    dojo.hitch(foo, "bar")();
    //        runs foo.bar() in the scope of foo
    //    example:
    //    |    dojo.hitch(foo, myFunction);
    //        returns a function that runs myFunction in the scope of foo
    //    example:
    //        Expansion on the default positional arguments passed along from
    //        hitch. Passed args are mixed first, additional args after.
    //    |    var foo = { bar: function(a, b, c){ console.log(a, b, c); } };
    //    |    var fn = dojo.hitch(foo, "bar", 1, 2);
    //    |    fn(3); // logs "1, 2, 3"
    //    example:
    //    |    var foo = { bar: 2 };
    //    |    dojo.hitch(foo, function(){ this.bar = 10; })();
    //        execute an anonymous function in scope of foo
    
    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
};

上述示例中,有些变量来自于lang.js文件中的定义。比如d是dojo的别名。

dojo.hitch的核心是Function.apply方法。我们直接用apply方法改写出一个简单的例子:

var foo = {
     bar: function(a, b, c){
         console.log(a, b, c);
     }
 };
foo.bar.apply(foo, [1,2,3]);

foo.bar是一个Function对象,因此拥有apply方法。注意为了能保存当前的上下文,dojo.hitch在最后一句中创建了一个闭包并将之返回。

关于dojo.hitch,还有一些事情要指出来,第一,它的method参数可以是Function,也可以是字符串(在scope里引用到一个函数)。第二,dojo.hitch允许函数除引用scope里的变量还,还可以临时指定参数(以数组的形式传递进去)。它通过d._hitchArgs函数来完成闭包的生成。第三,注释里提到可以用这种方法来模拟带缺省参数的函数,实际上这种方法并不实用。在注释的示例中,它实际上是声明了一个函数别名fn,来完成函数foo同样的事情。在c++/java语言里,c++直接支持缺省参数,java可以通过override来实现。Javascript里实现缺省参数函数也应该使用同java一样的方法。


国产化办公新选择:在银河麒麟V10上部署ToDesk远程桌面 本文详细介绍了在国产操作系统银河麒麟V10上部署ToDesk远程桌面的完整指南。作为国产远程控制工具,ToDesk在连接速度、系统适配性和用户体验方面表现优异,特别适合国产化办公场景。文章包含X86和ARM架构的安装步骤、常见问题排查及性能优化技巧,帮助用户高效实现远程办公。 阅读详情

相关推荐

MEG预处理-Brainstorm

Brainstorm下载和安装 去Brainstorm官网进行下载:打开网页后,点击左侧Download;在跳出来的界面中进行简单的注册,注册完成后可以进行下载 解压后得到“brainstorm3”的文件夹,里面包含Brainstorm工具包的所有文件,把这个文件夹放在某个路径如"E:\matlab_tools\brainstorm3"即可 同样在某个路径建立空的文件夹命名为:brainstorm_db用于工具包运行过程中自动存储生成的文件,所以这个文件中生成的数据不要手动移动删除 在Matlab中,把.

AxeChen的博客 6124

JavaScript中的函数调用以及dojo中lang.hitch()方法

  首先,了解两个概念JavaScript中的this关键字和JavaScript函数的执行环境。 JavaScript 语言中的 this   由于其运行期绑定的特性,JavaScript 中的 this 含义要丰富得多,它可以是全局对象、当前对象或者任意对象,这完全取决于函数的调用方式。JavaScript 中函数的调用有以下几种方式:作为对象方法调用,作为函数调用,作为构造函数调用,和使...

weixin_30872867的博客 265

思科模拟器PT8.2实战:用MQTT协议搭建智能家居控制原型(附完整代码)

本文详细介绍了如何在思科模拟器Packet Tracer 8.2中,利用MQTT协议构建一个智能家居灯光控制原型。从环境准备、拓扑设计到MQTT代理配置,手把手指导您完成发布者与订阅者的Python代码编写,实现开关对LED的远程控制。通过此实战项目,您将深入理解MQTT协议在物联网中的核心应用,掌握从理论到实践的完整开发流程。

weixin_29281941的博客 361

javascript中的闭包以及dojo中的dojo.hitch()

一、javascript的高级特性--闭包   理解closure前,首先明白函数作用域的概念。也就是全局变量和局部变量。在函数体内部可以调用全局变量,而函数体内被申明的变量不能被外部调用。       比较特殊的是,在js中,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!   其次,要理解javascript中的垃圾回收机制,在Javascript

GeoTechMAN's Zone 588

基于Isaac Gym与PPO算法的机械臂抓取任务仿真与强化学习实战(附完整代码与训练策略)

本文详细介绍了基于Isaac Gym与PPO算法的机械臂抓取任务仿真与强化学习实战。通过环境搭建、PPO算法实现、奖励函数设计等核心环节的优化,结合完整代码与训练策略,显著提升机械臂抓取效率与成功率。特别适合开发者快速掌握强化学习在机器人控制领域的应用。

weixin_29256771的博客 600

AVL(Athena Vortex Lattice)如何编写与应用(一)

前两个是弦向的涡个数和以cos函数分布的间距参数(设为1即可)后两个可以在这里声明也可以写到后面的每一个section中,是展向的涡个数和以sin函数分布的间距参数。这个文件是用来建立飞机模型的文件,是一定要有的文件,其他的.run和.mass并不是必须要有的,甚至mass文件并没有看到有人在使用。Sref、Cref、Bref是飞机的参考面积参考弦长和参考的展长,我的理解就是所设计飞机的S,c,b这三个参数。———————————————以上是飞机的基本信息———————————————

dawangaa的博客 1510

dojo中lang.hitch()的简单用法

函数上下文环境 这个概念经常会让很多刚接触javascript的开发者感到疑惑,尤其当其和this联系在一起说的时候。例如:Java中的方法是在编译时绑定到类,其中的this在调用方法的时候总是会指向包含此方法的类的实例。另一方面,JavaScript函数的上下文环境不是由函数在哪里定义而决定的,而是由它的调用方式决定的。

3529

学Simulink——基于扩展卡尔曼滤波(EKF)的列车牵引电机转子温度在线估计仿真

本文介绍了一种基于扩展卡尔曼滤波(EKF)的列车牵引电机转子温度在线估计方法,通过Simulink建模实现。文章首先阐述了EKF在估计电机转子温度中的优势,即利用易测量信号(如电流、电压、转速)在线估计难以直接测量的转子温度,并分析了温升对电机性能的影响。随后详细讲解了电机热电增广模型的构建,包括定子电阻温度关系、一阶热近似模型和PMSM的dq轴方程。接着,文章提供了Simulink建模的详细步骤,包括PMSM+FOC电流环的搭建、EKF算法的实现(推荐使用ExtendedKalmanFilter块或MAT

xiaoheshang_123的博客 56

Dojo中一些挺有意思的小功能(一)——hitch

用Dojo也有几年了,平常写代码的时候,经常碰到一些小小的需求,实现的功能不大,但是如果要自己编程的话,得费不少的劲儿。结果回头查Dojo的文档,竟然能找到一个功能,恰好能解决手头的需求,能惹得会心一笑。 忙中偷闲,这儿零零碎碎地把这样的小功能记录下来,聊以一乐。   文中所记功能是基于Dojo1.7.3的,想来更高的基于AMD的版本也有类似的功能。   dojo/_base/lang:

沧海一粟 —— 技术随手记 2505

SAP HANA CDS View Syntax Options 全解:从语法到工程实践

本文面向SAP HANA工程师,深入解析CDS视图的语法与应用场景。文章涵盖XS Advanced环境下的CDS视图设计要点,包括SELECT基础语法、聚合函数与分组约束、参数化视图实现以及常见连接操作。特别强调工程实践中的注意事项:GROUP BY禁用表达式、原生表名大小写规范、结果集裁剪方式选择等。通过两个真实案例(办公室占用率统计和客户画像分析)展示CDS视图在实际业务中的应用,并提供性能优化建议。全文采用中英文混排规范,技术术语使用反引号标注,旨在为开发者提供清晰的CDS视图开发指南。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 212

OpenOCD入门到精通:第20章 Target 子系统源码分析

摘要:本章深入分析OpenOCD Target子系统的核心实现机制。重点包括:1) 通过target_type虚函数表实现多架构抽象,支持ARM、RISC-V等30+种目标;2) ARM ADIv5协议栈实现,包含DAP/AP核心数据结构和访问机制;3) 分层架构设计,从调试接口层到传输层的完整调用链路。系统采用面向对象思想,统一管理目标状态、寄存器缓存、断点/观察点等调试要素,为上层提供标准化的调试操作接口。

从事嵌入式linux android驱动开发,拥有全栈能力 178

深入浅出 JavaScript 中的 this

原文地址:http://www.ibm.com/developerworks/cn/web/1207_wangqf_jsthis/index.html 简介: JavaScript 是一种脚本语言,因此被很多人认为是简单易学的。然而情况恰恰相反,JavaScript 支持函数式编程、闭包、基于原型的继承等高级功能。本文仅采撷其中的一例:JavaScript 中的 this 关键字,深入浅出的分析...

weixin_33901641的博客 65

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

告诉一个你不知道的this细节

JavaScript作为一种脚本语言身份的存在,因此被很多人认为是简单易学的。然而情况恰恰相反,JavaScript支持函数式编程、闭包、基于原型的继承等高级功能。由于其运行期绑定的特性,JavaScript 中的 this 含义要丰富得多,它可以是全局对象、当前对象或者任意对象,这完全取决于函数的调用方式。JavaScript中函数的调用有以下几种方式:作为对象方法调用,作为函数调用,...

auhe20308的博客 134

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

dojo异步编程之dojo/Deferred

dojo/Deferred介绍 dojo/Deferred是一个类,是Dojo中管理异步线程的基础。 简单来说,一个Deferred对象会等待一段时间再去执行指定的调用,直到某个特定的事件发生或者前一个动作完成。Ajax就是一种常见的例子: 发出一个Ajax请求之后,我们需要等待服务器把响应返回之后才会调用处理函数。所以Deferred对象提供给我们的就是这种将某个动作延迟并等待某个事件发生的能...

shiyangxu的博客 1146

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Dojo 调用 js中的方法

HTML代码: 按钮 var dojoConfig = { async: true, //此代码寄存器的“演示”包正确的位置,所以我们可以从CDN加载Dojo的同时还能够加载本地模块 packages: [{

炘的专栏 5736

dojo异步编程 dojo/Deferred

Email:longsu2010 at yeah dot net JavaScript的事件回调真的很棒,比如AJAX获取数据在数据返回时执行某函数,比如websocket获取数据后执行某函数,比如JSONP…… dojo的dojo/Deferred用于开启一个异步程序,对于封装通用组件特别有用。 下面介绍dojo/Deferred的用法, 从一个小例子开始。(本例使用chrome)requ...

v5browser 263

javascript中的闭包以及dojo中的dojo.hitch

  一、javascript的高级特性--闭包   理解closure前,首先明白函数作用域的概念。也就是全局变量和局部变量。在函数体内部可以调用全局变量,而函数体内被申明的变量不能被外部调用。 比较特殊的是,在js中,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!   其次,要理解javascript中的垃圾回收机制,在Jav...

ajm3017的博客 208

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

原文:http://dojotoolkit.org/documentation/tutorials/1.7/hitch/ 原文作者:Tom Trenka 译者:Ruan Qi Dojo 1.7 难度级别:中级 在dojo工具包中,dojo/_base/lang模块对Javascript原生方法进行了包装或增强,提供了不少相当有用的方法。本文将介绍Javascript中的函数对象(Functio...

web开发自学 216

Dojo 扩展 javascript 核心库 - dojo.hitch

dojo.hitch 是在 Dojo 中直接或间接被广泛使用的函数. hitch 的中文意思是: 钩住,拴住. 在 Dojo 中, dojo.hitch() 的作用是给一个方法绑定其执行上下文. 在 Dojo 中, dojo.hitch 函数非常重要. 原因有两点:  1. Javascript 中, 函数不与定义它们的上下文即作用域绑定 2. 在 Dojo 中, 很多函数都用 h

Patrick's 专栏 4542

dojo事件机制详解(一)

概述 dojo中的事件实现并不复杂,当然我只是从代码量的角度出发,但含金量还是很高的,而且很容易实现自定义事件监听,还支持发布订阅模式,下面我们从源代码级别来看看 dojo中的事件机制是如何实现的,深入了解后,甚至可以将其拷贝出来直接就能在其它使用。 事件机制使用中主要涉及以下4个函数: 1. dojo.connect(); 建立事件监听连接 2. dojo.disconnect();

云原生之家 3223

部分Dojo常用函数简介(四)——String及Array扩展

每个Ajax 框架都对Javascript 做了扩展,提供了很多常用函数,增强了 Javascript 的开发效率。在这里将对部分Dojo 中的常用函数做简单的介绍。由于Dojo的常用函数较多,也为方便大家阅读,将这些常用函数分为了五个类别分别进行介绍。本文将介绍第四部分的内容:String及Array扩展。

Dojo中文博客 9667

Dojo 1.7的新功能-aspect

AOP广泛用在日志,性能统计,安全审计,事务管理等地方,极大地减小了程序员对这些杂务的关注,同时获得了更好的处理一致性和重构的灵活性。 尽管动态语言有着非常有利于实现AOP的特性,但到目前为止,Javascirpt领域还没有很好的AOP实现。Dojo 1.7在这方面迈开了第一步

博客只是岁月的记录 2362

Dojo class中跟变量相关的几个问题

Fire an event manually Dojo class中跟变量相关的几个问题   2011 年 11 月 09 日 | dojo 针对 Java 开发人员的 Dojo 概念是学习dojo不得不读的一篇文章。本文对该文中没有详尽讲述的的跟变量相关的几个问题做一些阐述。 引文中在“复杂的类属性”一节,举例如下: dojo.declare( "myCla

博客只是岁月的记录 2292

Aptana 3的dojo API doc(更新)

Aptana 3提供的API doc没有包含doh这一部分,本站加入了对doh的支持。同时,将原文件折分成3个,更便于编辑和查阅(并不是所有的时候code assist都好使,这时候就需要直接打开文档自己找)。 下载dojo.1.6.0.dojo.sdocml 下载dojo.

博客只是岁月的记录 1928
上一篇: 理解和解决IE的内存泄漏模式
下一篇: 向网页动态注入dojo工具包
yaaron
博客等级 码龄19年 7粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值