add(2)(3)(4) 输出 9
其实这可以理解为
add(2) 返回函数A A(3) 返回函数B B(4) 返回函数C C函数运行的最终结果为 9
那么最初的做法可以是:
js
function add(n1) {
var sum = 0
sum += n1
return function(n2) {
sum += n2
return function(n3) {
sum += n3
return sum
}
}
}
var result = add(2)(3)(4) // 9考虑其他的扩展性,若要求调用4次或者2次等,则上面的函数就不能满足这样的需求了。
那为什么不满足呢? 其原因是我们最后返回的结果是 sum 一个变量值,而不是函数对象。
那么,按前面的写法,改一下,使之继续返回函数:
js
function add(n1) {
var sum = 0
sum += n1
return function(n2) {
sum += n2
return function(n3) {
sum += n3
return function(nn) {/* xxx */}
}
}
}问题是要调用的次数是未知的。就此可以利用链式调用,让函数返回后返回自身
js
function add(n1) {
var sum = 0
sum += n1
return function add2(n2) {
sum += n2
return add2
}
}上述函数执行返回的结果是函数对象的字符串表示,怎样让之变位输出结果呢?
- 在函数中添加判断,当没有输入参数时,直接返回调用的结果而不是返回函数
js
function add(n1) {
var sum = 0
sum += n1
return function add2(n2) {
if (arguments.length === 0) return sum
sum += n2
return add2
}
}在调用时,需要多加一个()
js
var result = add(2)(3)(4)(5)() // 14- 利用JS对象到原始值的转换规则
当一个对象转换成原始值时,先查看对象是否有valueOf方法,如果有并且返回值是一个原始值,那么直接返回这个值;否则没有valueOf或返回的不是原始值,那么调用toString方法,返回字符串表示
我们就位函数对象添加一个valueOf方法和toString方法
js
function add(n1) {
var sum = 0
if (arguments.length === 0) return sum
sum += n1
var add2 = function(n2) {
if (arguments.length === 0) return sum
sum += n2
return add2
}
add2.valueOf = () => sum
add2.toString = () => sum + ''
return add2
}
add(1)(2)(3)(4) // function 10 这是toString返回的所以是字符串
add(1)(2)(3)(4)() // 10 number类型js
function add(n1) {
let sum = 0
sum += n1
function add2(n2) {
if (arguments.length === 0) return sum
sum += n2
return add2
}
add2.valueOf = () => sum
add2.toString = () => sum + ''
return add2
}另一种实现方法
js
var add = (function() {
var args = []
function add2() {
if (arguments.length === 0) {
return calRet
} else {
Array.prototype.push.apply(args, Array.prototype.splice.call(arguments, 0))
return add
}
}
function calRet() {
var result = args.reduce((acc, val) => acc + val, 0)
args = []
return result
}
add2.valueOf = () => calRet()
add2.toString = () => calRet() + ''
return add2
})()