Freewind @ Thoughtworks scala java javascript dart 工具 编程实践 月结 math python english [comments admin] [feed]

(2012-05-15) Nodejs中如何给函数的部分参数预设值(部分应用函数)

广告: 云梯:翻墙vpn (省10元) 土行孙:科研用户翻墙http proxy (有优惠)

在nodejs中,可以利用bind,实现对函数的部分参数预设值,得到一个新函数供以后使用。

这个bind实际上是ecmascript5中新增的功能,这里举例说明。

首先定义一个普通的函数:

function add(a,b) { return a+b; }

通常的调用方式:

add(1,3); // -> 4

add(1,5); // -6

利用bind可以给add预设一些值,如下:

var x = add.bind(null, 3);

x(2); // -> 5

x(100) // -> 103

在某些情况下会比较有用。

其中bind的函数签名与call相很似,第一个参数(null)是准备调用该函数的对象,与参数无关,对于我们这个例子来说,就是null。后面的3,对应的是参数a。

举个不为null的例子:

var obj = {
method: function(name){

console.log(name);       

}
};
var x1 = obj.method.bind(obj);
x1(“John”); // -> John

var x2 = obj.method.bind(obj, “Jack”);
x2(); // -> Jack

再来一个异步的例子:

var inc = function(n, cb) {

setTimeout(function() {       
    cb(null, n+1);       
}, 1000);       

}

var x = inc.bind(null, 4);

x(function(err,result) {

console.log(result);       

});

我为什么对这个特性很感兴趣呢?因为它可以简化我们的代码。

先看这个例子(使用了async):

var async = require('async');

var inc = function add(n, cb) {

setTimeout(function() {       
    cb(null, n+1);       
}, 200);       

};

async.series([

function(cb) { inc(3,cb); },       
function(cb) { inc(8,cb); }       

], function (err,result) {

console.log(result);       

});

其中async.series的第一个参数,都要用一些function包在外面,感觉有点繁琐。如果利用bind,可写成:

async.series([

inc.bind(null,3),       
inc.bind(null,8)       

], function(err, result) {

console.log(result);       

});

简化了不少吧:)

稍有遗憾的是,由于javascript的语言特性,如果函数中有多个参数,bind只能按顺序预设,不能跳过前面预设后面。比如:

add(a,b)

只能绑定a,或者(a,b),但不能只绑定b。

一些评论

AlsoTang

https://gist.github.com/3745456

这是一个更加准确的关于js中bind的示例。

comments powered by Disqus