我试图理解在实践中使用JavaScript中的功能样式的方法。我已经创建了一组简单的函数来处理字符串,但我觉得我在概念上做错了,因为它看起来就像命令式样式,即使我不改变输入并且不改变应用程序内部的状态功能
以下是它的外观:
var LineParser = require('../modules/LineParser');
var inputLine = 'A line with multiple spaces';
var outputLine = LineParser().formatSpaces(inputLine);
// 'A line with multiple spaces'
outputLine = LineParser().capitalize(outputLine);
// 'A Line With Multiple Spaces'
outputLine = LineParser().formatSomethingElse(outputLine);
// Some more formatting, then do further processing with outputLine
如果我使用回调运行序列,那么当我有10个简单的处理函数时,它会很快变成一组丑陋的嵌套回调函数。
如果我添加方法链接,原型方法的想法也会与功能样式相反,因为链中的函数将取决于先前的状态,而不仅仅取决于它们得到的输入。
我应该怎样做才能让它在功能风格上更好看?
更新:经过深入研究后,我找到了名为Function Composition的主题。它似乎是解决问题的正确方法,也是功能世界的基本内容之一。 这是我用来将多个函数组合成一个函数的函数:
var compose = function () {
var funcs = arguments;
return function () {
var args = arguments;
for (var i = funcs.length; i-- > 0;) {
args = [funcs[i].apply(this, args)];
}
return args[0];
};
};
然后我做了一个作文:
var composedFunction = compose(func1, func2, ..., funcn)
从右到左运行,一切正常。
答案 0 :(得分:0)
您的直排队员似乎有formatSpaces
,capitalize
和formatSomethingElse
等方法。你可以做的最简单的事情是将所有这些方法都设置为return this
,这样你就可以将这些方法链接起来:
var outputline = LineParser.formatSpaces(inputLine).capitalize().formatSomethingElse()
虽然从外观上看,所有方法都需要一些字符串作为参数,因此您可能需要进行一些实现更改,例如在给定的情况下将字符串保存在私有变量中,如果没有参数则从变量中提取它给出了。
答案 1 :(得分:-1)
如果你想要异步编程,但是你不喜欢嵌套的回调,你考虑过async lib吗? 你可以这样:
var LineParser = require('../modules/LineParser');
var inputLine = 'A line with multiple spaces';
async.waterfall([
function(callback) {
var result = LineParser().formatSpaces(inputLine);
callback(null, result);
},
function(arg1, callback) {
var result = LineParser().capitalize(arg1);
callback(null, result);
},
function(arg1, callback) {
var result = LineParser().formatSomethingElse(arg1);
callback(null, result);
}
], function (err, result) {
// retrieve the final string
});
如果你将LineParser方法修改为异步方法,那么可以变成有用的东西(否则它只会使你的3行更重)
答案 2 :(得分:-1)
功能风格,即我们在Lisp等中看到的纯函数风格如下所示:
var outputline = formatSomethingElse(capitalize(formatSpaces(inputline)));
通常,为了便于阅读,它的格式为:
var outputline = formatSomethingElse(
capitalize(
formatSpaces(inputline)
)
);
任何其他形式都不是功能风格。功能样式有点像反向波兰表示法,因为所述操作应该反向读取。实际上,RPN本身就是一种函数式编程语法(由Forth体现)。
有一种风格与功能风格相似:方法链:
var outputline = LineParser(inputline)
.formatSpaces()
.capitalize()
.formatSomethingElse()
.toString();
与功能样式不同,方法链接按顺序读取。
虽然最着名的链接库jQuery会改变对象的状态,但实际上并不是必需的。以LineParser
:
function LineParser (text) {
return {
text: text,
toString: function () {return this.text},
capitalize: function () {
// return a new object instead of "this"
return {
text : _capitalize(this.text),
toString : this.toString
}
}
}
}