JavaScript咖喱:有什么实际的应用?
-
02-07-2019 - |
题
我不认为我grokked扩充。我了解它做什么,以及如何做到这一点。我只是不能认为的情况下,我会使用它。
你在哪里使用扩充在JavaScript(或其中的主要图书馆使用它的)?DOM操纵或一般应用程序开发的例子值得欢迎的。
其中一个答案 提到,动画。功能等 slideUp
, fadeIn
采取一个元素作为一个参数,并通常都是一个咖喱功能返回的高秩序的功能,与默认"的动画功能的"。为什么比这更好的只申请较高职能与一些默认值?
是否有任何缺点使用?
要求这里有一些很好的资源JavaScript扩充:
- http://www.dustindiaz.com/javascript-curry/
- Crockford,道格拉斯(2008年) JavaScript:好的部分
- http://www.svendtofte.com/code/curried_javascript/ (需要一个迂回到毫升所以跳过整个部分,从"一毫升",并开始再一次在"如何编写扩充JavaScript")
- http://web.archive.org/web/20111217011630/http://blog.morrisjohns.com:80/javascript_closures_for_dummies
- 怎么JavaScript封锁的工作?
- http://ejohn.org/blog/partial-functions-in-javascript (先生Resig上的钱如往常一样)
- http://benalman.com/news/2010/09/partial-application-in-javascript/
我会添加更多,因为他们的作物中的评论意见。
因此,据答案,扩充和局部应用程序一般是便利技术。
如果你经常"提炼"一个高级别的功能通过调用它与相同的结构,可以咖喱(或使用Resig的部分)的更高级别的功能,以创造简单的、简洁的辅助方法。
解决方案
@汉克是同性恋
在响应EmbiggensTheMind的评论:
我不能想到的一个实例 讨好—通过本身是有用的,在JavaScript;这是一个技术转换功能的电话有多个参数纳入链的功能调用的一个参数的每个电话,但JavaScript支持多个参数,在一个单一功能的电话。
在JavaScript—我假设大多数其他实际的语言(不氧微积分)—这是常见的相关部分应用程序,虽然。约翰Resig 解释的更好, 但其要旨是,有一些逻辑,即将应用于两个或两个论点,你只是知道的价值(s)对于其中一些论点。
你可以使用的局部应用程序/扩充,以解决已知的那些价值观和返回的一个功能,只能接受未知数,可以调用的后来,当你实际上有价值你愿意通过。这提供了一个极好的方式,以避免重复自己的时候你会被呼吁同JavaScript建件过与所有相同的价值观只有一个。偷走约翰的例子:
String.prototype.csv = String.prototype.split.partial(/,\s*/);
var results = "John, Resig, Boston".csv();
alert( (results[1] == "Resig") + " The text values were split properly" );
其他提示
这里有一个 有趣和实用的扩充在JavaScript使用的关闭:
function converter(toUnit, factor, offset, input) { offset = offset || 0; return [((offset + input) * factor).toFixed(2), toUnit].join(" "); } var milesToKm = converter.curry('km', 1.60936, undefined); var poundsToKg = converter.curry('kg', 0.45460, undefined); var farenheitToCelsius = converter.curry('degrees C', 0.5556, -32); milesToKm(10); // returns "16.09 km" poundsToKg(2.5); // returns "1.14 kg" farenheitToCelsius(98); // returns "36.67 degrees C"
这依赖于一个 curry
延长 Function
, 虽然如你可以看到它的唯一用途 apply
(没有什么太花哨):
Function.prototype.curry = function() { if (arguments.length < 1) { return this; //nothing to curry with - return function } var __method = this; var args = toArray(arguments); return function() { return __method.apply(this, args.concat([].slice.apply(null, arguments))); } }
我找到的职能类似于蟒蛇的 functools.partial
更有用的JavaScript:
function partial(fn) {
return partialWithScope.apply(this,
Array.prototype.concat.apply([fn, this],
Array.prototype.slice.call(arguments, 1)));
}
function partialWithScope(fn, scope) {
var args = Array.prototype.slice.call(arguments, 2);
return function() {
return fn.apply(scope, Array.prototype.concat.apply(args, arguments));
};
}
为什么你要用它?一个常见的情况下,你想要用这个时候你想要结合 this
在一个功能值:
var callback = partialWithScope(Object.function, obj);
现在当回调是所谓, this
点到 obj
.这是有用的,在事件的情况下,或保存某些空间,因为它通常使代码短。
扩充的相似部分的差异功能的扩充的回报只是接受一个参数(如我了解那)。
同意汉克是同性恋-这是非常有用,在某些真实的功能编程语言-因为这是一个必要部分。例如,在Haskell,你根本无法采取多种参数的一个函数-你不能这样做,在纯粹的功能程序。你需要一个参数的时间和建立自己的功能。在JavaScript它只是不必要的,尽管有预谋的例子,如"换算"。这里是同样的代码转换器,而不需要扩充:
var converter = function(ratio, symbol, input) {
return (input*ratio).toFixed(2) + " " + symbol;
}
var kilosToPoundsRatio = 2.2;
var litersToUKPintsRatio = 1.75;
var litersToUSPintsRatio = 1.98;
var milesToKilometersRatio = 1.62;
converter(kilosToPoundsRatio, "lbs", 4); //8.80 lbs
converter(litersToUKPintsRatio, "imperial pints", 2.4); //4.20 imperial pints
converter(litersToUSPintsRatio, "US pints", 2.4); //4.75 US pints
converter(milesToKilometersRatio, "km", 34); //55.08 km
我严重的愿望的道格拉斯Crockford,在"JavaScript:好的部分",曾给出一些说的历史和实际使用的扩充,而不是他的offhanded发言。时间最长的阅读后,我猛然一惊,直到我是在学习的功能编程和实现,这是从哪里来的。
后一些更多的思考,我断定有一个有效的使用情况,用于扩充在JavaScript:如果你想写使用纯粹的功能编程技术的使用JavaScript。似乎是一个罕见的使用情况。
这是一个例子。
我检测到一堆场字所以我可以看看有什么用户。代码看起来是这样的:
$('#foo').focus(trackActivity);
$('#foo').blur(trackActivity);
$('#bar').focus(trackActivity);
$('#bar').blur(trackActivity);
(为非。。用户,我是说,任何时候,一对夫妇的领域得到或失去了重点,我希望trackActivity()function被称为。我还可以用一名匿名的功能,但我必须重复它的4倍,所以我拉出来和命名。)
现在,事实证明,一些领域需要不同的方式处理。我想要能够通过一个参数之一的这些呼吁被传递给我们的跟踪基础设施。用讨好的,我可以。
这是有魔法或任何东西...只是一个愉快的速记匿名的功能。
partial(alert, "FOO!")
相当于 function(){alert("FOO!");}
partial(Math.max, 0)
对应 function(x){return Math.max(0, x);}
在呼吁部分(MochiKit 术语。我认为一些其他图书馆得到的功能。咖喱方法,该方法做同样的事情)看起来稍微更好和噪音小于匿名的功能。
作为对图书馆使用,总是有 功能.
当它是有用的,在JS?可能是同样的时候,它是有用的,在其他现代语言,但是只有时间我可以看到自己使用它,是结合局部应用程序。
我要说,最有可能,所有的动画图书馆在JS使用讨好.而不是具有通过对各呼叫一组受影响的要素和功能,描述如何件应表现,一个更高阶功能,这将确保所有的时间的东西,其通常更便于客户释放,作为公共API一些功能,如"slideUp","淡入",只需要要素作为论据,只是一些咖喱功能返回的高秩序的功能,与默认"的动画功能的"。
JavaScript功能是所谓的lamda在其他功能性的语言。它可以被用于撰写新api(更强大或complext功能)的基础上的另一个开发者的简单的输入。咖喱仅仅是一个技术。你可以用它来创建一个简化的api叫一个复杂的。如果你是develper谁使用的简化api(例如使用jQuery做到简单的操作),则不需要使用咖喱。但如果你想要建立简化的api,咖喱是你的朋友。你必须要写一个javascript框架(如jQuery脱)或图书馆,然后你可以理解它的力量。我写了一个增强的咖喱的功能, http://blog.semanticsworks.com/2011/03/enhanced-curry-method.html .你不需要咖喱的方法来做到扩充,它只是帮助做到扩充,但你总是可以做手工编写一个function A(){}返回的另一个function B(){}.为了使它更有趣,使用function B()返回的另一个function C().
我知道它的旧线,但我将必须表明这是如何被使用在javascript库:
我会用lodash.js 图书馆来描述这些概念的具体。
例如:
var fn = function(a,b,c){
return a+b+c+(this.greet || ‘');
}
局部应用程序:
var partialFnA = _.partial(fn, 1,3);
扩充:
var curriedFn = _.curry(fn);
结合:
var boundFn = _.bind(fn,object,1,3 );//object= {greet: ’!'}
使用:
curriedFn(1)(3)(5); // gives 9
or
curriedFn(1,3)(5); // gives 9
or
curriedFn(1)(_,3)(2); //gives 9
partialFnA(5); //gives 9
boundFn(5); //gives 9!
差异:
之后讨好我们得到了一个新的功能没有参数的预先约束。
之后的部分应用中,我们得到一个功能,这势必有一些参数prebound.
在结合我们可以结合背景下,这将被用来取代'这个',如果不能默认的任何功能将窗口的范围。
建议:没有必要重新发明车轮。局部应用程序/结合的/扩充非常相关。你可以看到的差异上。使用这个意义上的任何地方,人们会认出你是什么做没问题的了解,再加上你将要使用较少的代码。
我同意,在次你会喜欢的球滚动通过创建一个伪功能,总是会有价值的第一个参数。幸运的是,我碰到一个全新的JavaScript库称为jPaq(http://jpaq.org/)提供这种功能。最好的事情有关图书馆的事实是,你可以载你的自己的建立,它仅包含码,你会需要。
我刚写了一jPaq例,它显示了一些很酷的应用程序的咖喱的功能。看看这里: 扩充了串职能
只是想添加一些资源Functional.js:
讲座/会议于说明一些应用程序 http://www.youtube.com/watch?v=HAcN3JyQoyY
更新Functional.js 图书馆:https://github.com/loop-recur/FunctionalJS 一些很好的帮手(对不起,新来的,没有声誉:p):/循环再次出现/PreludeJS
我一直使用这个图书馆很近,以减少重复在js因诺琴蒂研究中心客户的助手图书馆。这是伟大的东西-真的可以帮助清理和简化的代码。
此外,如果性能成为一个问题(但是,这lib是漂亮的灯光),很容易只是重写,使用当地的功能。
你可以使用当地结合为快速的一线解决方案
function clampAngle(min, max, angle) {
var result, delta;
delta = max - min;
result = (angle - min) % delta;
if (result < 0) {
result += delta;
}
return min + result;
};
var clamp0To360 = clampAngle.bind(null, 0, 360);
console.log(clamp0To360(405)) // 45
另一个刺它的工作与承诺。
(免责声明:JS小白,来自蟒蛇的世界。即使在那里, 讨好 不用那么大,但它可以在方便的场合。所以我三份文件的内容的扩充功能看到的链接)
首先,我开始与阿贾克斯的电话。我有一些具体的处理上做的成功,但在失败,我只是想得到的用户反馈调 的东西 导致 一些错误.在我的代码,我显示错误的反馈在引导小组,但我只是用记录在这里。
我已经修改我的生活url使这种失败。
function ajax_batch(e){
var url = $(e.target).data("url");
//induce error
url = "x" + url;
var promise_details = $.ajax(
url,
{
headers: { Accept : "application/json" },
// accepts : "application/json",
beforeSend: function (request) {
if (!this.crossDomain) {
request.setRequestHeader("X-CSRFToken", csrf_token);
}
},
dataType : "json",
type : "POST"}
);
promise_details.then(notify_batch_success, fail_status_specific_to_batch);
}
现在,在这里为了告诉用户的一批失败了,我需要写这些信息中的错误处理,因为它所得到的响应从服务器。
我还是仅有的信息可在编码的时间-在我的情况下,我有一些可能的批次但是我不知道哪一个已经失败。o.分析的服务的响应关于失败的网址。
function fail_status_specific_to_batch(d){
console.log("bad batch run, dude");
console.log("response.status:" + d.status);
}
让我们做它。控制台输出为:
控制台:
bad batch run, dude
utility.js (line 109)
response.status:404
现在,让我们改变的事情一点,并使用可重复使用的通用处理程序失败,但还有一个是 咖喱 在运行时既已知的-在码时的上下文和运行时的信息可从事件。
... rest is as before...
var target = $(e.target).text();
var context = {"user_msg": "bad batch run, dude. you were calling :" + target};
var contexted_fail_notification = curry(generic_fail, context);
promise_details.then(notify_batch_success, contexted_fail_notification);
}
function generic_fail(context, d){
console.log(context);
console.log("response.status:" + d.status);
}
function curry(fn) {
var slice = Array.prototype.slice,
stored_args = slice.call(arguments, 1);
return function () {
var new_args = slice.call(arguments),
args = stored_args.concat(new_args);
return fn.apply(null, args);
};
}
控制台:
Object { user_msg="bad batch run, dude. you were calling :Run ACL now"}
utility.js (line 117)
response.status:404
utility.js (line 118)
更一般地说,鉴于广泛回调,使用在JS,扩充似乎是一个很有用的工具。
https://javascriptweblog.wordpress.com/2010/04/05/curry-cooking-up-tastier-functions/ http://www.drdobbs.com/open-source/currying-and-partial-functions-in-javasc/231001821?pgno=2