可选的参数 (Arguments Optional)
题目链接
问题解释
- 这个
function
在定义的时候没有声明任何参数,但在调用的时候会传入一个或者两个参数。最后返回两数之和 - 如果参数是一个,那么调用方式就是
add(1)(2)
的形式,返回值为3
- 如果参数是两个,那么调用方式就会是
add(1, 2)
的形式,返回值也为3
基本解法
思路提示
- 相比之前几道题,这道题稍有难度,但整体逻辑并不复杂
- 通过分析我们得知,只有传入一个参数或两个参数,这两种情况:
- 如果传入一个参数,那就需要再通过
(x)
传入第二个参数 - 如果传入两个参数,直接返回两个参数之和就行
- 如果传入一个参数,那就需要再通过
- 既然
add
函数中没有声明参数,因此这道题我们肯定是要用arguments
来操作了 - 另外还有一点需要考虑,就是如何判断参数是否为数字。你可能第一反应是使用
isNaN
方法来判断,事实上在这道题目中是不够的。因为左边的测试有一条是add(1, "2")
也应该返回undefined
,可以先考虑下这个要如何处理 - 另外就是,这道题会用到一点点闭包的知识。闭包可能是刚开始学 JS 接触到的最大难点。对此,我个人的建议是不用过于深究闭包的定义。多写写代码,自然会遇到需要使用闭包的情况。或者很可能你已经会写闭包了,但只是不知道它叫闭包
参考链接
代码
1 | function add() { |
解释
- 先从最好解释的说起吧。这里封装了一个用于判断是否为数字的
isNum
方法。由于题目中只允许数字,不允许字符串或者其它,那么最容易想到的就是通过typeof
了,这样就可以直接过滤掉字符串 - 但这也会带来其他问题。对于
typeof
返回number
的不光有数字,还有NaN
以及Infinity
。如果你不知道Infinity
,可以去搜搜看,这也是一个关键字。如果用一个数除以0
,你也会得到Infinity
- 因此,我们需要在后面加上
isFinite
来判断,它可以帮我们过滤掉NaN
以及Infinity
这两种情况。虽然类似与isFinite("1")
也会返回true
,但我们已经有了typeof
那个判断 - 另外,虽然这里没有涉及,但要多说一句。
isFinite
这个方法,如果传入[]
或者只有一个数字元素的数组,比如[3]
,那是会返回true
的。由于isFinite([1, 2])
就会返回false
,因此我猜测原因是调用了数组的toString
方法,把[3]
变成了"3"
- 第一行代码,再多说一句吧,以前提到过几次。
arguments
和nodeList
是 JavaScript 中常见的 “Array-like object” (类数组对象)。它本身没有数组方法,对象中的属性是0
、1
、2
、3
…… 这样的。上面的代码,意思就是把它转成一个数组 - (补充): 写完才想到,这里其实不转也行。因为 “Array-like object” 是有
length
属性的,后续代码中我们也只有访问元素和访问length
这两个操作。但是,强烈建议这里赋一下值,因为对于一个参数的情况,我们要返回一个匿名函数,这时候在内部函数也会有一个arguments
- 返回两数的和应该没什么多说的。题目中只有两种情况,有兴趣的朋友可以尝试一下,能不能写成可以接收不定数目参数的,类似于
add(1, 2, 3)(4)(5, 6)(7)(8)
。这个实现起来会更加有挑战 - 关键在于后面那个
return function
,其实这一部分,我自己刚开始学 JS 的时候也懵了很久。我们可以这么去理解,add(2)(3)
这样的调用方式,其实就是在add(2)
执行之后,(3)
执行之前的那个瞬间是一个函数,我们暂且称这个函数为function foo() {}
。那么,foo(3)
就很好理解了,相当于把3
作为参数传入foo
。简单画个图:
1 | function foo() {} |
- 这样画是想说明,对于这里说的那个
foo
函数,根据题目要求,我们只需要在定义的时候让它接收一个参数就好了,也就是图中的3
- 那么,如果我们把
add
函数的返回值设置成上面说到的foo
函数 (确切一点说,是返回foo
函数的引用),那么它就可以通过add(2)(3)
这样的形式来调用了,并且3
会传到foo
里面去 - 既然
foo
是add
函数的返回值,那么foo
本身就是在add
函数里面的。根据 JS 的作用域特点,在函数foo
里面我们可以访问到add
函数作用域中的值,这也就是我们获取第一步传入的2
的思路 - 再考虑一下,在
add
函数中,反正foo
也就只在最后执行一次,那我们没必要在add
里给它命名。因此才有了上面返回一个匿名函数的写法,那个最后返回的匿名函数就是这里我们说的foo