为了编写具有良好可读性的高质量代码,我采用currying functions方法并为大多数重复代码片段制作纯辅助函数。我刚观察到我的项目中到处都存在/类型检查,以避免任何可能的错误,例如type of undefined.
支票如下:
if (param){
action...
}
我正在考虑创建一个应该采用两个参数的全局辅助函数;需要检查的param
和action function
以便在检查通过时执行操作。类似的东西:
function isExist(param, action){
if (param){
action();
}
}
此功能并非适用于所有代码段/案例。如何使其在所有情况下都高效且全局运行?这也是正确的方法。如果没有那么我在这里实现目标的最佳方法是什么?
示例:
if (userInput){
saveToDB(userInput);
}
if (valueFromDB){
performSomeAction();
}
if (username && password){
validate(username, password)
}
我希望我的代码中不同点的所有这些检查都被单个辅助函数替换为:
isExist( userInput, saveToDB(userInput) );
isExist( valueFromDB, performSomeAction );
isExist( (username && password), validate(username, password) );
通过这种方式,我们用三行代替了这9行代码。这就是我想要达到的目标。
答案 0 :(得分:2)
好吧,如果你试着想出一个好名字
function isExist(param, action){
if (param){
action();
}
}
然后我认为一个好的候选人将是conditionalExecute(condition, codeToExecute)
。这种工作听起来很熟悉吗?你确定你不只是重新发明if语句吗?
也许我错过了你的观点,但我个人看不到封装if语句逻辑的好处比现在更多。
编辑:应该注意在Javascript的上下文中代码
if(someVariable){
// do something
}
已经读过"如果someVariable
是truthy(undefined
不是)那么....
但是可以肯定的是,如果你只是想检查是否存在(一个变量没有被定义),如果你说它有一个更明确的命名功能,那么我不会反对你。
在这种情况下,我认为仅仅封装实际存在检查(或者你想要检查的内容)更清楚,而不是条件性(因为我们已经有了if语句)。像
这样的东西function exists(x) {
return x !== undefined; // or something like that
}
function isNotNull(x) {
//TODO:
}
然后您的代码将变得更加明确和可读,如果您愿意,您可以组合这些功能
function neitherUndefinedNorNull(x){
return exists(x) && isNotNull(x);
}
if(neitherUndefinedNorNull(X)){
// your "regular" code here
}
如果重复了if语句中的代码,那么也将其作为函数提取。
function myRepeatedCode() {
// do stuff
}
function someAlternativeCondition(x){
// test
}
if(neitherUndefinedNorNull ){
myRepeatedCode();
} else if(someAlternativeCondition(x)) {
myRepeatedCode();
}
// OR combine them in the same if-statement
if(neitherUndefinedNorNull(x) || someAlternativeCondition(x)){
myRepeatedCode();
}
上次修改:如果你正在追逐角色,你甚至可以写
// because of short-circuiting, myFunc1 and myFunc2 will only
// execute if myCond1 resp myCond2 is true (or truthy).
myCond1(x) && myFunc1(x)
myCond2(y) && myFunc2(y)
答案 1 :(得分:2)
这是使用Maybe
的理想场所:
const enumerable = true;
// data Maybe a = Nothing | Just a
const Maybe = {};
const Nothing = Object.create(Maybe);
const Just = value => Object.create(Maybe, {value: {enumerable, value}});
// instance Functor Maybe where
Nothing.map = _ => Nothing;
Maybe.map = function (fun) { return Just(fun(this.value)); };
// instance Applicative Maybe where
Maybe.of = Just;
Nothing.ap = _ => Nothing;
Maybe.ap = function (maybe) { return maybe.map(this.value); };
// instance Monad Maybe where
Nothing.chain = _ => Nothing;
Maybe.chain = function (kleisli) { return kleisli(this.value); };
Maybe
跟随Fantasy Land Specification [1] 。使用Maybe
可以编写如下代码:
// userInput :: Maybe Data
// saveToDB :: Data -> Something
userInput.map(saveToDB); // :: Maybe Something
// valueFromDB :: Maybe Data
// performSomeAction :: Data -> Maybe Something
valueFromDB.chain(performSomeAction); // :: Maybe Something
// username :: Maybe String
// password :: Maybe Password
// validate :: String -> Password -> Something
Maybe.of(validate).ap(username).ap(password); // :: Maybe Something
无论如何,如果你真的对函数式编程感兴趣,那么我建议你Learn You A Haskell。
[1] 我不同意flipping the arguments of ap
上的幻想土地规范。
答案 2 :(得分:1)
怎么样,它可以同时处理参数。
function test(a,b,c)
{
console.log("%s,%s,%s",a,b,c)
}
function check_and_run(param,action){
var args = Array.prototype.slice.call(arguments); //turn arguments to array
args.shift(); //remove param and action
args.shift();
if(param)
action.apply(this,args)
}
check_and_run(1,test,1,2,3) //this will invoke test(1,2,3)
check_and_run(0,test,1,2,3) //this will do nothing
答案 3 :(得分:1)
也许是这样的:
function conFun(fnCondition, fnCall, defaultResult=undefined) {
return (...rest) => {
if( fnCondition(...rest) ) {
return fnCall(...rest)
}
return defaultResult;
}
}
const add = conFun(
(...rest) => rest.every(n => typeof n === 'number'),
(...rest) => rest.reduce((a, n) => a+n),
NaN);
add("1", "2"); //=> NaN
add(1, 2); //=> 3
所以在你的问题中,你可能会在第一个参数未被定义之后:
const firstDefined = (v) => typeof v !== 'undefined';
const cSomeFun = conFun(firstDefined, someFun, "");
cSomeFun(); // ==> ""
cSomeFun("test"); // ==> whatever someFun("test") returns
如果你只是想根据非未定义的参数调用某些东西,你可以简单地定义它:
function callDefined(fn, ...rest) {
if( rest.every(firstDefined) ) {
return fn(...rest)
}
return undefined;
}
callDefined( saveToDB.bind(this, userInput), userInput);
callDefined( performSomeAction, valueFromDB);
callDefined( calidate.bind(this, username, password), username, password);