JavaScript Patterns 4.10 Curry
Function Application
apply() takes two parameters: the first one is an object to bind to this inside of the function, the second is an array or arguments, which then becomes the array-like arguments object available inside the function. If the first parameter is null, then this points to the global object, which is exactly what happens when you call a function that is not a method of a specific object.
// define a function
var sayHi = function(who) {
return "Hello" + ( who ? ", " + who : "") + "!";
};
// invoke a function
sayHi();
// "Hello"
sayHi('world');
// "Hello, world!"
// apply a function
sayHi.apply(null, ["hello"]);
// "Hello, hello!"
//-----------------------------------------------------------------------
var alien = {
sayHi : function(who) {
return "Hello" + ( who ? ", " + who : "") + "!";
}
};
alien.sayHi('world');
// "Hello, world!"
sayHi.apply(alien, ["humans"]);
// "Hello, humans!"
In the preceding snippet, this inside of sayHi() points to alien. In the previous example this points to the global object.
When you have a function that takes only one parameter, you can save the work of creating arrays with just one element:
// the second is more efficient, saves an array sayHi.apply(alien, ["humans"]); // "Hello, humans!" sayHi.call(alien, "humans"); // "Hello, humans!"
Partial Application
var add = function(x, y) {
return x + y;
};
// full application
add.apply(null, [5, 4]);
//
// partial application
var newadd = add.partialApply(null, [5]);
// applying an argument to the new function
newadd.apply(null, [4]);
//
Here’s no partialApply() method and functions in JavaScript don’t behave like this by default. But you can make them, because JavaScript is dynamic enough to allow this. The process of making a function understand and handle partial application is called currying.
// a curried add()
// accepts partial list of arguments
function add(x, y) {
var oldx = x, oldy = y;
if ( typeof oldy === "undefined") {// partial
return function(newy) {
return oldx + newy;
};
}
// full application
return x + y;
}
// test
typeof add(5);
// "function"
add(3)(4);
//
// create and store a new function
var add2000 = add(2000);
add2000(10);
//
General-purpose currying function
function schonfinkelize(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);
};
}
// a normal function
function add(x, y) {
return x + y;
}
// curry a function to get a new function
var newadd = schonfinkelize(add, 5);
newadd(4);
//
// another option -- call the new function directly
schonfinkelize(add, 6)(7);
//
// a normal function
function add(a, b, c, d, e) {
return a + b + c + d + e;
}
// works with any number of arguments
schonfinkelize(add, 1, 2, 3)(5, 5);
//
// two-step currying
var addOne = schonfinkelize(add, 1);
addOne(10, 10, 10, 10);
//
var addSix = schonfinkelize(addOne, 2, 3);
addSix(5, 5);
//
When to Use Currying
When you find yourself calling the same function and passing mostly the same parameters, then the function is probably a good candidate for currying. You can create a new function dynamically by partially applying a set of arguments to your function. The new function will keep the repeated parameters stored (so you don’t have to pass them every time) and will use them to pre-fill the full list of arguments that the original function expects.
References:
JavaScript Patterns - by Stoyan Stefanov (O`Reilly)
JavaScript Patterns 4.10 Curry的更多相关文章
- JavaScript Patterns 2.10 Naming Conventions
1. Capitalizing Constructors var adam = new Person(); 2. Separating Words camel case - type the word ...
- JavaScript Patterns 7.1 Singleton
7.1 Singleton The idea of the singleton pattern is to have only one instance of a specific class. Th ...
- JavaScript Patterns 6.7 Borrowing Methods
Scenario You want to use just the methods you like, without inheriting all the other methods that yo ...
- JavaScript Patterns 6.6 Mix-ins
Loop through arguments and copy every property of every object passed to the function. And the resul ...
- JavaScript Patterns 6.5 Inheritance by Copying Properties
Shallow copy pattern function extend(parent, child) { var i; child = child || {}; for (i in parent) ...
- JavaScript Patterns 6.4 Prototypal Inheritance
No classes involved; Objects inherit from other objects. Use an empty temporary constructor function ...
- JavaScript Patterns 6.3 Klass
Commonalities • There’s a convention on how to name a method, which is to be considered the construc ...
- JavaScript Patterns 6.2 Expected Outcome When Using Classical Inheritance
// the parent constructor function Parent(name) { this.name = name || 'Adam'; } // adding functional ...
- JavaScript Patterns 6.1 Classical Versus Modern Inheritance Patterns
In Java you could do something like: Person adam = new Person(); In JavaScript you would do: var ada ...
随机推荐
- 使用ActivityManager实现进程管理
Android中使用ActivityManager可以获得进程信息,并对进程进行管理,如结束进程等.本文使用ActivityManager获得进程列表,并结束选中的进程. 首先,看看布局文件. < ...
- hibernate----component-entity (人-地址-学校)
package com.ij34.dao; import javax.persistence.*; @Entity @Table(name="school_inf") public ...
- 修正 XE6 TListView 上方 SearchBok 右边的清除钮显示
注意:XE7 已修正这个问题. Delphi Firemonkey TListView 提供了搜寻的功能,但在 XE6 以前的版本,可以显示右边的清除按钮,在 XE6 确消失了,这里提供一个修正的方案 ...
- 从零开始学Python04作业思路:模拟ATM电子银行
标签(空格分隔):Python 一,程序文件说明 程序分为5个组成部分 bin:放置Python程序的启动接口文件 通过Python命令启动文件夹内文件即正常执行Python程序 例如:ATM_sta ...
- 用Apache 里面的ab做一个简单的压力测试
我用的是xampp环境包. D:\xampp\apache\bin 进入这路径, 找到ab.exe 尝试双击打开ab.exe 但不能如愿, 这两个都是一个压力的测试软件, 是apache自带的; 好 ...
- php错误处理-错误处理
错误类型 因为错误类型整型值的巧妙设定,可以采用按位运算符 1 E_ERROR (integer) 致命的运行时错误.这类错误一般是不可恢复的情况,例如内存分配导致的问题. 导致脚本终止不再继续运行 ...
- <welcome-file-list>标签的控制作用以及在springmvc中此标签的的配置方式
我们在写安全性较高的网站时必然会对网站的入口进行限制, 而在这其中其关键作用的就是网站的根目录下WEB-INF中的web.xml中<welcome-file-list> <welc ...
- Use a cache
To create high-performance systems, sometimes you need to cache data. Play has a cache library and w ...
- windows.open()、close()方法详解
windows.open()方法详解: window.open(URL,name,features,replace)用于载入指定的URL到新的或已存在的窗口中,并返回代表新窗口的Win ...
- JavaScript学习笔记-对象
枚举对象的属性:通常用for(...in...)来循环遍历,由于 for in 总是要遍历整个原型链,因此如果一个对象的继承层次太深的话会影响性能 for(var i in foo){ if(foo. ...