JavaScript 中的链函数
Chain functions in JavaScript
有没有一种方法可以在 JavaScript 中链接函数,因此当调用链中的最后一个函数时,我们会考虑指定的链中的所有函数。
基本上我想做的是同一件事 express-validator
做:
像这样:
check('password').passwordValidator().optional();
我希望能够打电话给
check('password').passwordValidator();
和
check('password').passwordValidator().optional();
所以您正在寻找一种 builder pattern?你可以这样做:
class Foo {
_passwordValidator = false;
_optional = false;
passwordValidator() {
this._passwordValidator = true;
return this;
}
optional() {
this._optional = true;
return this;
}
doThing() {
if (this._optional) { /* ... */ }
if (this._passwordValidator) { /* ... */ }
}
}
const foo = new Foo().passwordValidator().optional();
foo.doThing();
编辑:为了更直接地回答您的问题,没有办法等到当前的方法调用链完成后再做某事;您必须在示例中调用类似 doThing()
的方法,以表明您现在确实想做这件事。
调用 express-validator
returns 中间件函数的链式方法,并且由于函数可以具有属性,您可以在返回的函数上调用方法,returns 一个新函数方法等。链接函数非常简单:
const chain = (pairs, fn = el => el) => {
for(const [key, method] of pairs)
fn[key] = (...opt) => chain(pairs, method(fn)(...opt));
return fn;
};
const math = chain([
["add", prev => a => b => prev(b) + a],
["mul", prev => a => b => prev(b) * a]
]);
console.log(
(math.add(5).mul(3).add(3))(5)
);
我最终使用了@coolreader18 建议的内容。
这正是我要找的。
function func(val) {
this._optional = false;
this._check = false;
const doStaff = (message = 'Doing staff') => {
console.log(message);
return;
};
return {
check: function(n) {
this._check = true;
return this;
},
optional: function(n) {
this._check = false;
this._optional = true;
return this;
},
exec: function() {
if (this._check) doStaff();
if (this._optional) doStaff('Maybe not');
}
}
}
func().check().optional().exec();
var Obj = {
result: 0,
addNumber: function(a, b) {
this.result = a + b;
return this;
},
multiplyNumber: function(a) {
this.result = this.result * a;
return this;
},
divideNumber: function(a) {
this.result = this.result / a;
return this;
}
}
Obj.addNumber(10, 20).multiplyNumber(10).divideNumber(10);
link => https://medium.com/technofunnel/javascript-function-chaining-8b2fbef76f7f
这个解决方案的灵感来自 React setState:
function pipe/*<U>*/(val/*: U*/) {
return {
case: function (condition/*: boolean*/, value/*: U | ((prop: U) => U)*/) {
if (condition) {
if (value instanceof Function) {
return pipe(value(val));
} else {
return pipe(value);
}
} else {
return pipe(val);
}
},
valueOf: function () {
return val;
},
};
}
const result = pipe(2)
.case(false, 3)
.case(true, (current) => current + 2)
.case(false, 4)
.valueOf();
console.log(result) // 4
有没有一种方法可以在 JavaScript 中链接函数,因此当调用链中的最后一个函数时,我们会考虑指定的链中的所有函数。 基本上我想做的是同一件事 express-validator 做: 像这样:
check('password').passwordValidator().optional();
我希望能够打电话给
check('password').passwordValidator();
和
check('password').passwordValidator().optional();
所以您正在寻找一种 builder pattern?你可以这样做:
class Foo {
_passwordValidator = false;
_optional = false;
passwordValidator() {
this._passwordValidator = true;
return this;
}
optional() {
this._optional = true;
return this;
}
doThing() {
if (this._optional) { /* ... */ }
if (this._passwordValidator) { /* ... */ }
}
}
const foo = new Foo().passwordValidator().optional();
foo.doThing();
编辑:为了更直接地回答您的问题,没有办法等到当前的方法调用链完成后再做某事;您必须在示例中调用类似 doThing()
的方法,以表明您现在确实想做这件事。
调用 express-validator
returns 中间件函数的链式方法,并且由于函数可以具有属性,您可以在返回的函数上调用方法,returns 一个新函数方法等。链接函数非常简单:
const chain = (pairs, fn = el => el) => {
for(const [key, method] of pairs)
fn[key] = (...opt) => chain(pairs, method(fn)(...opt));
return fn;
};
const math = chain([
["add", prev => a => b => prev(b) + a],
["mul", prev => a => b => prev(b) * a]
]);
console.log(
(math.add(5).mul(3).add(3))(5)
);
我最终使用了@coolreader18 建议的内容。 这正是我要找的。
function func(val) {
this._optional = false;
this._check = false;
const doStaff = (message = 'Doing staff') => {
console.log(message);
return;
};
return {
check: function(n) {
this._check = true;
return this;
},
optional: function(n) {
this._check = false;
this._optional = true;
return this;
},
exec: function() {
if (this._check) doStaff();
if (this._optional) doStaff('Maybe not');
}
}
}
func().check().optional().exec();
var Obj = {
result: 0,
addNumber: function(a, b) {
this.result = a + b;
return this;
},
multiplyNumber: function(a) {
this.result = this.result * a;
return this;
},
divideNumber: function(a) {
this.result = this.result / a;
return this;
}
}
Obj.addNumber(10, 20).multiplyNumber(10).divideNumber(10);
link => https://medium.com/technofunnel/javascript-function-chaining-8b2fbef76f7f
这个解决方案的灵感来自 React setState:
function pipe/*<U>*/(val/*: U*/) {
return {
case: function (condition/*: boolean*/, value/*: U | ((prop: U) => U)*/) {
if (condition) {
if (value instanceof Function) {
return pipe(value(val));
} else {
return pipe(value);
}
} else {
return pipe(val);
}
},
valueOf: function () {
return val;
},
};
}
const result = pipe(2)
.case(false, 3)
.case(true, (current) => current + 2)
.case(false, 4)
.valueOf();
console.log(result) // 4