Javascript/ Typescript .bind() get Variable in bound functio



我想将变量绑定到回调函数,但猫鼬已经将一个名为val的参数嵌入到该函数中。当我想使用 .bind(( 将另一个值绑定到回调函数时,我丢失了原始的 val 属性。有没有办法保留原始参数并将带有 .bind(( 的变量添加到其中? 下面是一个示例。

// gets val parameter from validator
const maxLengthValidator = (val: string): boolean => {
if (val.length > 255) return false;
return true;
};
const userSchema = new Schema({
email: {
type: String,
required: true,
// unique: true
validate: [
{
validator: maxLengthValidator, // includes a val attribute from post request
msg: 'too short'
},
]
},
password: {
type: String,
required: true
}
});
export default model('User', userSchema);

我想做什么:

// gets val parameter from validator
const maxLengthValidator = (val: string, boundary: number): boolean => {
if (val.length > boundary) return false;
return true;
};
...
validate: [
{
validator: maxLengthValidator.bind(this, 255), // doesn't work, would need to specify the string for the val parameter
msg: 'too short'
},
]
...

所以我可以在验证器对象中设置最大长度。

咖喱

您可以更改函数,因此它不需要接受两个参数,而是接受一个参数,然后返回第二个函数,该函数接受第二个参数。这种已知的技术被称为咖喱。

// maxLengthValidator :: number -> string -> boolean 
const maxLengthValidator = (boundary: number) => (val: string) : boolean  => {
if (val.length > boundary) return false;
return true;
};
// ... later ...
validator: maxLengthValidator(255);

通过这种方式,您可以通过调用函数来创建不同的验证器:maxLengthValidator(10)将为您提供可以使用的 10 个字符的验证器。由于它是一个函数,你也可以把它分配给一个变量:

//userNameLengthValidator :: string -> boolean
const userNameLengthValidator: (val: string) => boolean = maxLengthValidator(10);

交换参数以适应部分分配

与其取值然后取最大长度,不如先取长度。与柯里函数相同,但这个仍然可以采用两个参数:

const maxLengthValidator = (boundary: number, val: string): boolean => {
if (val.length > boundary) return false;
return true;
};
// ... later ...
validator: maxLengthValidator.bind(this, 255);

相同的基本思想。不过,这次你有更多的灵活性 - 你可以maxLengthValidator(10, username)两个参数调用函数,或者只用一个参数部分应用它。后者产生与currying几乎相同的东西,因为你仍然会得到一个具有相同签名的新函数:

//userNameLengthValidator :: string -> boolean
const userNameLengthValidator: (val: string) => boolean = maxLengthValidator.bind(this, 10);

尽管有相似之处,但咖喱不是部分应用。此外,可以柯理任何参数(任意数量的参数(的函数,以便一次取一个或多个。例如,您可以在 Lodash 中看到_.curry

function add4(a, b, c, d) {
console.log(a + b + c + d);
}
const curryAdd4 = _.curry(add4); 
curryAdd4(1)(2)(3)(4);
curryAdd4(1, 2, 3, 4);
curryAdd4(1)(2, 3)(4);
curryAdd4(1, 2, 3)(4);
curryAdd4(1)(2, 3, 4);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>

使用占位符或从右侧部分应用

您可以保持签名不变,只需更改部分应用程序即可。Function#bind不是很灵活,但您可以编写自己的库或(更好的是(使用库。我将再次使用 Lodash,因为它对这些有很好的实现:

带占位符的部分应用程序

允许您在部分应用时跳过某些参数。因此,您可以跳过第一个,只需设置第二个:

const maxLengthValidator = (val, boundary) => {
if (val.length > boundary) return false;
return true;
};
//userNameLengthValidator :: string -> boolean
const usernameLengthValidator = _.partial(maxLengthValidator, _, 10);
console.log(usernameLengthValidator("usernameTooLong"));
console.log(usernameLengthValidator("user"));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>

从右侧部分应用

从右到左开始部分应用,因此它将首先设置boundary

const maxLengthValidator = (val, boundary) => {
if (val.length > boundary) return false;
return true;
};
//userNameLengthValidator :: string -> boolean
const usernameLengthValidator = _.partialRight(maxLengthValidator, 10);
console.log(usernameLengthValidator("usernameTooLong"));
console.log(usernameLengthValidator("user"));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>

最新更新