这是我正在谈论的一个例子:
使用grunt,你有这个功能:
grunt.file.match([options, ] patterns, filepaths)
在文档中,他们说:
patterns和filepaths参数都可以是单个字符串或字符串数组。
那么,为同一个参数允许不同的类型是一个好习惯吗?
答案 0 :(得分:3)
简而言之,是的。在其他语言中,您可以重载具有不同参数的方法。在javascript中,你没有这种奢侈,但我们所拥有的是弱类型声明。所以javascript并不关心你传递的内容,确保你的函数接受所有可能的参数是你的工作。
修改强>
正如@ jwatts1980建议的那样,你的函数应该足够灵活,以便处理任何潜在的参数。如果您有一个名为name
的参数,您应该偶尔会null
,并且有可能让您收到names
数组,在这种情况下您可能会选择迭代超过names
(name
)并对name
进行任何操作。
答案 1 :(得分:1)
优良作法是在单个数据和数据集合之间进行不可知。这使得功能导向的代码能够很好地流动,因为它可以促进#34;单例到数组。功能人员(例如Haskell程序员)将能够更全面地解释这一点,但根据我作为程序员的经验,我肯定会回答#34; yse"与此同时。
答案 2 :(得分:1)
对于某些函数,很自然地假设输入可以有多种形式,并且允许它通常可以产生更优雅的API。
在单值vs数组的情况下,您可能希望将参数转换为数组有很多原因。
当您编写处理数据转换的函数时尤其如此。如果同时支持值和列表,则可以通过函数体的主要部分以统一的方式对其进行操作。
// triple everything passed to it
math.triple = function(xs) {
if(!(xs instanceof Array)) {
xs = [xs];
}
var txs = xs.map(function(x) {
return x * 3;
});
return txs.length > 1 ? txs : txs[0];
};
以统一的方式处理数据是一个非常强大的概念。您不必担心两个代码路径(每个输入类型一个)或编写全新的函数(重载)。
用户不必担心记住将输入包装到数组中。
math.triple(3); // 9
math.triple([1, 2, 3]); // [3, 6, 6]
在这种情况下,区别在于函数和值,而不是列表和值。
function map(array, value) {
var fn = value,
transformed = [];
if(typeof value !== 'function') {
fn = function() { return value };
}
array.forEach(function(item) {
transformed.push(fn(item));
});
return transformed;
}
我们可以用map
来实现forEach
,新地图函数将采用值或函数。
// old map
[1, 2, 3].map(function() { return 0; }); // [ 0, 0, 0 ]
// old map
[1, 2, 3].map(0); // TypeError: 0 is not a function
// new map
map([1, 2, 3], 0); // [ 0, 0, 0 ]
// new map
map([1, 2, 3], function() { return 0; }); // [ 0, 0, 0 ]
新版本的地图更加强大,因为它支持两种类型的变换,并且可以在精神上保存用户一些时间,记住功能名称和物理,因为语法更轻。
尝试使您编写的每个函数都支持多种不同的选项是一个坏主意。你永远无法记住它们,编写测试会很痛苦,而且会让那些必须使用它们的人感到困惑。你会无意中引入很多错误,因为你的大脑很难弄清楚函数究竟会对一组给定的参数做些什么。
在某些情况下,吸收参数是合适的,但不是经常这样,当你认为它是合适的时候,那么你也注册编写清晰的文档来解释它。
答案 3 :(得分:0)
优秀的做法是记录您的功能并解释其启发式(如果它使用的话)。接受不同类型输入的函数可以非常直观地调用,或者它可能导致意外行为。特别是在String vs Array的情况下,因为它们在某种程度上具有相似的行为(都具有整数索引属性和长度),并且有人可能合理地希望将字符串视为字符数组某些情况,以及其他情况下的单一价值。