如何改造JS柯里化add函数使其执行后直接返回数字类型而非函数对象
问题说明
你当前实现的add函数支持柯里化链式调用,在隐式转换场景下会展示为求和结果,但实际返回值类型为函数,需要实现返回严格数字类型,满足console.log(typeof ext.add(1)) // number的效果。
核心矛盾说明
传统的同步链式柯里化求和方案,依赖返回函数实现连续调用,重写
toString/valueOf仅能实现隐式转换为数字,无法改变变量本身的函数类型,要实现严格数字类型返回,需要对调用逻辑做调整,以下是三种可选实现方案:
方案1:放弃链式调用,直接返回数字
如果不需要支持ext.add(3, 1)()(3)这类连续调用,直接修改add逻辑,调用即返回求和结果:
function Ext() { let cs = 0; return { add: function add(...num) { const sum = num.reduce((a, b) => a + b, 0); cs += sum; return sum; } } } const ext = Ext(); console.log(typeof ext.add(1)) // number console.log(ext.add(1) === 1) // true console.log(ext.add(3,1)) // 4
注意:该方案无法支持链式调用,ext.add(1)(2)会抛出类型错误
方案2:保留链式调用,无参数时自动返回数字
调整逻辑,链式调用阶段返回可执行函数,传入空参数调用时直接返回数字类型的结果:
function Ext() { let cs = 0; function pars(fn) { let newFn = fn.bind(null); function cal(...num) { // 无参数传入时直接返回计算结果 if(num.length === 0) { const res = newFn(); newFn = fn.bind(null); return res; } newFn = newFn.bind(null, ...num); return cal; } // 保留隐式转换能力兼容旧逻辑 cal.toString = () => newFn(); cal.valueOf = () => newFn(); return (...num) => { newFn = fn.bind(null); return cal(...num); }; } const _add = pars((...num) => { num.forEach((item) => { cs += item; }); return num.reduce((a, b) => a + b, 0); }); return { add: function add(...num) { return _add(...num); } } } const ext = Ext(); console.log(ext.add(1)()) // 1 console.log(typeof ext.add(1)()) // number console.log(ext.add(3,1)()(3)()) // 7 console.log(typeof ext.add(3,1)()(3)()) // number
方案3:异步Promise实现(匹配你注释中的思路)
将返回值改为Promise,异步返回数字类型的结果:
function Ext() { let cs = 0; function pars(fn) { let newFn = fn.bind(null); function cal(...num) { newFn = newFn.bind(null, ...num); return cal; } cal.toString = () => newFn(); cal.valueOf = () => newFn(); return (...num) => { newFn = fn.bind(null); return cal(...num); }; } const _add = pars((...num) => { num.forEach((item) => { cs += item; }); return num.reduce((a, b) => a + b, 0); }); return { add: function add(...num) { return new Promise(resolve => { const result = _add(...num); resolve(Number(result)); }) } } } const ext = Ext(); ext.add(1).then(res => { console.log(typeof res) // number console.log(res === 1) // true })
注意:该方案返回值为Promise类型,无法直接同步拿到数字结果
内容的提问来源于stack exchange,提问作者trek89
相关产品推荐
相关产品推荐

