简单来说,柯里化技术是为了扁平化处理多参数的函数,提高函数的适用性。
实现逻辑:把一个多参数的目标函数,变成接受部分参数的函数,同时该函数用来接收目标函数的剩余参数。
柯里化是 js 闭包特性的经典使用场景。
举例:
function add(x, y) {
return x + y;
}
console.log(add(1, 2)); // 3
柯里化后:
function add(x) {
return function (y) {
return x + y;
}
}
console.log(add(1)(2)); // 3
将相同的参数固定下来。
// eg: 正则验证字符串 reg.test(txt)
// 函数封装后
function check(reg, txt) {
return reg.test(txt)
}
// 即使是相同的正则表达式,也需要重新传递一次
console.log(check(/\d+/g, 'test1')); // true
console.log(check(/\d+/g, 'testtest')); // false
console.log(check(/[a-z]+/g, 'test')); // true
// 柯里化后
function curryingCheck(reg) {
return function (txt) {
return reg.test(txt)
}
}
// 正则表达式通过闭包保存了起来
var hasNumber = curryingCheck(/\d+/g)
var hasLetter = curryingCheck(/[a-z]+/g)
console.log(hasNumber('test1')); // true
console.log(hasNumber('testtest')); // false
console.log(hasLetter('21212')); // false
实现效果如下,具体参考这篇文章 element-plus 架构 - BEM和命名空间
const ns = useNamespace('button')
ns.b() // el-button
ns.b('group') // el-button-group
ns.m('primary') // el-button--primary
ns.em('text', 'expand') // el-button__text--expand
ns.is('disabled', true) // is-disabled
元素绑定事件的工具函数,参考 element-ui 的源码
export const on = (function() {
if (!isServer && document.addEventListener) {
return function(element, event, handler) {
if (element && event && handler) {
element.addEventListener(event, handler, false);
}
};
} else {
return function(element, event, handler) {
if (element && event && handler) {
element.attachEvent('on' + event, handler);
}
};
}
})();
注意到 on
是立即执行函数,执行后返回一个新函数,这样会提前确认用哪个方法,避免每次都做判断。
实现细节:curry 工具函数 curry
接受的参数个数不确定,但第一个参数一定是目标函数fn
,剩下的参数是目标函数原本的参数 ...args
,curry
的返回值也是一个函数_curry
,用来接受目标函数剩下的参数。
并且在调用_curry
时,会判断传递给_curry
的参数个数 + 之前传递给 curry
的参数个数之和,是否满足目标函数的个数。
如果是,则执行原本的目标函数;否则继续调用 _curry
并传递目标函数剩下的参数。
function curry(fn, ...args) {
// 函数的 length 是函数的参数个数
if (args.length === fn.length) {
return fn(...args)
}
return function _curry(...params) {
args.push(...params)
if (args.length === fn.length) {
return fn(...args)
}
return _curry
}
}
function add(a, b, c) {
return a + b + c
}
console.log(curry(add, 1, 2, 3)) // 6
console.log(curry(add, 1)(2)(3)) // 6
console.log(curry(add)(1)(2)(3)) // 6
以上。