Dojo学习笔记(七):Making Functions with hitch and partial
2014-10-13 23:22
447 查看
dojo/_base/lang包含两个有用的方法:lang.hitch和lang.partial。lang.hitch主要负责修改this运行上下文,lang.partial主要负责修改函数参数个数,进行函数签名。
1、JavaScript 中的运行上下文(execution contexts)
在JavaScript中,当一个函数被调用,一个运行上下文就被创建出来。上下文的创建经过如下阶段:
(1)arguments 参数对象的创建;
(2)函数作用域 scope 的创建;
(3)函数中变量 Variables 的实例化;
(4)this 属性(指向上下文 context 自身) 的创建。
this 属性是绝大多数开发者都会混淆的地方;它其实就是一个指向函数调用时作为上下文context(或叫作用域 scope)的对象的引用,在 JavaScript 中,函数执行时的实际上下文,是在函数被调用时才决定的。
作用域 (scope),它就是个对象,既可以作为方法函数调用执行时的空间,也可以作为方法函数、属性等的定义空间。后面会讲到词法作用域(lexical scope),可以认为为这是 JavaScript 中真正的作用域,词法作用域使用了闭包技术closures。
函数调用时的作用域(scope) ,在JavaScript中称为运行上下文(execution context)。
The value of foo is undefined, from node-1
The value of foo is undefined, from node-2
The value of foo is undefined, from node-3
分析原因:
期望的结果是显示显示"The value of 'foo' is bar",但我们得到信息:The value of 'foo' is undefined。
(1)node.onclick = myObject.myHandler
在这里 myObject.myHandler 经过解析,变成了函数 myHandler,仅仅是函数而已。而 myHandler 做为 myObject 的方法的这一事实被完全舍弃了。(将 myObject.myHandler 赋值给 onclick , context 什么事儿,它才不管这个函数在哪定义,他完全将这个函数同对象本身剥离了。)
(2)如果你依然困惑,只需要记住在 JavaScript中 Functions objects同其他非原始类型一样,是引用传递,而非值传递。在我们上面的例子中,我们不过将 onclick 设置为一个直接指向 myObject.myHandler的引用。
使用.apply和.call切换运行上下文execution contexts
(1)使用lang.hitch绑定运行上下文execution context
lang.hitch可以指定函数的上下文,关键代码:
arguments object 并非一个真正的JavaScript的Array object;尽管某些方面同数组类似(如采用数字下标索引,包含 length 属性等),但其是只读的,因此某些 Array 方法对其无效(如 Array.prototype.slice)。
(3)使用lang.partial修改函数签名function signatures
是不是很想把 htich 的优点(强制运行上下文)和partial的优点(预置参数)整合在一起?好吧,lang.hitch进一步增强可以完成以上两种工作:你可以在context和method 两个参数后,再添加任意数量的参数,lang.hitch 将会绑定上下文,预置参数,生成新的函数。
备注:hitch 和 partial 是通往函数式编程的入口(参考: functional programming);Dojo Toolkit 在 dojox/lang/functional 下提供了很多函数式编程技术东西,建议你有空看看。
本文出自 “IT技术学习与交流” 博客,谢绝转载!
1、JavaScript 中的运行上下文(execution contexts)
在JavaScript中,当一个函数被调用,一个运行上下文就被创建出来。上下文的创建经过如下阶段:
(1)arguments 参数对象的创建;
(2)函数作用域 scope 的创建;
(3)函数中变量 Variables 的实例化;
(4)this 属性(指向上下文 context 自身) 的创建。
this 属性是绝大多数开发者都会混淆的地方;它其实就是一个指向函数调用时作为上下文context(或叫作用域 scope)的对象的引用,在 JavaScript 中,函数执行时的实际上下文,是在函数被调用时才决定的。
作用域 (scope),它就是个对象,既可以作为方法函数调用执行时的空间,也可以作为方法函数、属性等的定义空间。后面会讲到词法作用域(lexical scope),可以认为为这是 JavaScript 中真正的作用域,词法作用域使用了闭包技术closures。
函数调用时的作用域(scope) ,在JavaScript中称为运行上下文(execution context)。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>dojoConfig</title> <style type="text/css"> .myNode { border: 1px solid #999; margin: 0.5em; padding: 0.5em; background-color: #ccc; float: left; } </style> <script src="dojo/dojo.js"></script> <script> // Retrieve the dependencies require(["dojo/query", "dojo/dom-construct", "dojo/domReady!"], function(query, domConstruct) { function log(msg){ var c = document.getElementById("console"); if(!c){ c = domConstruct.create("div", { id: "console" }, document.body); } c.innerHTML += "<div>" + msg + "</div>"; } var myObject = { foo: "bar", myHandler: function(evt){ //still contrived! //假设evt为事件对象:W3C标准中,使用evt.target,而IE为evt.srcElement log("The value of foo is " + this.foo + ", from " + (evt && evt.target ? evt.target.id : window.event.srcElement.id)); } }; var container = document.getElementById("nodeContainer"); for(var i=0; i<5; i++){ domConstruct.create("div", { id: "node-" + (i+1), className: "myNode", innerHTML: "Fake button " + (i+1) }, container); } query(".myNode").forEach(function(node){ node.onclick = myObject.myHandler; }); }); </script> </head> <body> <div id="nodeContainer"> </div> </body> </html>输出结果:
The value of foo is undefined, from node-1
The value of foo is undefined, from node-2
The value of foo is undefined, from node-3
分析原因:
期望的结果是显示显示"The value of 'foo' is bar",但我们得到信息:The value of 'foo' is undefined。
(1)node.onclick = myObject.myHandler
在这里 myObject.myHandler 经过解析,变成了函数 myHandler,仅仅是函数而已。而 myHandler 做为 myObject 的方法的这一事实被完全舍弃了。(将 myObject.myHandler 赋值给 onclick , context 什么事儿,它才不管这个函数在哪定义,他完全将这个函数同对象本身剥离了。)
(2)如果你依然困惑,只需要记住在 JavaScript中 Functions objects同其他非原始类型一样,是引用传递,而非值传递。在我们上面的例子中,我们不过将 onclick 设置为一个直接指向 myObject.myHandler的引用。
使用.apply和.call切换运行上下文execution contexts
query(".myNode").forEach(function(node){ node.onclick = function(evt){ myObject.myHandler.call(myObject,evt); }; });将触发绑定事件代码修改成如上内容,就可得到想要的结果。
(1)使用lang.hitch绑定运行上下文execution context
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>dojoConfig</title> <style type="text/css"> .myNode { border: 1px solid #999; margin: 0.5em; padding: 0.5em; background-color: #ccc; float: left; } </style> <script src="dojo/dojo.js"></script> <script> // Retrieve the dependencies require(["dojo/_base/lang","dojo/query", "dojo/dom-construct", "dojo/domReady!"], function(lang,query, domConstruct) { function log(msg){ var c = document.getElementById("console"); if(!c){ c = domConstruct.create("div", { id: "console" }, document.body); } c.innerHTML += "<div>" + msg + "</div>"; } var myObject = { foo: "bar", myHandler: function(evt){ //still contrived! log("The value of foo is " + this.foo + ", from " + (evt && evt.target ? evt.target.id : window.event.srcElement.id)); } }; var container = document.getElementById("nodeContainer"); for(var i=0; i<5; i++){ domConstruct.create("div", { id: "node-" + (i+1), className: "myNode", innerHTML: "Fake button " + (i+1) }, container); } query(".myNode").forEach(function(node){ node.onclick = lang.hitch(myObject, myObject.myHandler); }); }); </script> </head> <body> <div id="nodeContainer"> </div> </body> </html>说明:
lang.hitch可以指定函数的上下文,关键代码:
query(".myNode").forEach(function(node){ node.onclick = lang.hitch(myObject, myObject.myHandler); });(2)参数对象The arguments object
arguments object 并非一个真正的JavaScript的Array object;尽管某些方面同数组类似(如采用数字下标索引,包含 length 属性等),但其是只读的,因此某些 Array 方法对其无效(如 Array.prototype.slice)。
(3)使用lang.partial修改函数签名function signatures
query(".myNode").forEach(function(node){ //don't forget: method first, fixed arguments second! node.onclick = lang.partial(myObject.myHandler, myObject); });(4)将 hitch和partial 的优点整合在一起
是不是很想把 htich 的优点(强制运行上下文)和partial的优点(预置参数)整合在一起?好吧,lang.hitch进一步增强可以完成以上两种工作:你可以在context和method 两个参数后,再添加任意数量的参数,lang.hitch 将会绑定上下文,预置参数,生成新的函数。
备注:hitch 和 partial 是通往函数式编程的入口(参考: functional programming);Dojo Toolkit 在 dojox/lang/functional 下提供了很多函数式编程技术东西,建议你有空看看。
本文出自 “IT技术学习与交流” 博客,谢绝转载!
相关文章推荐
- Formulas and Functions with Microsoft Office Excel 2007
- Learning with python: Chapter3~4 Functions,Conditionals and Recursion
- Create Elegant Code with Anonymous Methods, Iterators, and Partial Classes
- [Ramda] Curry and Uncurry Functions with Ramda
- Professional SQL Server 2005 CLR Programming: with Stored Procedures, Functions, Triggers, Aggregates and Types
- Swift Standard Library: Documented and undocumented built-in functions in the Swift standard library – the complete list with all 74 functions
- 笔记:Structure-Constrained Low-Rank and Partial Sparse Representation with Sample Selection for image
- Making a small Lisp project with quickproject and Quicklisp
- [Ramda] Refactor to Point Free Functions with Ramda using compose and converge
- 【转载】Making new features with topology tools(ArcInfo and ArcEditor only)
- Statement based replication with Stored Functions, Triggers and Events
- Updating and Publishing a NuGet Package - Plus making NuGet packages smarter and avoiding source edits with WebActivator
- More Effective C++ 31. Making functions virtual with respect to more than one object
- Search Engine Optimization -Building Traffic and Making Money with SEO
- No way to generate HTML markup with data-link and helper functions in JsViews like in JsRender
- Making your Rails app mobile with WAP and WML
- Starting out with Node.js and AngularJS
- [Ramda] Difference between R.converge and R.useWith
- React with Visual Studio Code and Webpack
- Server-Side Paging with the Entity Framework and ASP.NET MVC 3