最近学弟去面了字节跳动,可是因为面试经验少,面试的时候紧张了,一时之间没有写出来,以后来我交流了一下。那我就来分析分析这道题目。javascript
这题的规则是这样的java
给定有一个 Add 函数,要支持如下形式的调用面试
Add(1)(2)(3).sumOf(); // 输出 6 Add(1,2)(3)(4).sumOf(); // 输出 10 Add(1,2,...)(3)(4)(...).sumOf(); // ...
拿到这种题目,我先来讲说我本身的作题流程,通常会去找它最简单的形态。咱们一步一步来拆解。segmentfault
先去掉 sumOf()
变成了如下形态数组
Add(1,2,...)(3)(4)(...)
嗯....有点熟悉...可是仍是有点复杂,那咱们再去掉无限调用这个限制。微信
Add(1,2,...)(3)(4)
唔,仍是有点难呀...不要紧,再砍, 不要传入多个参数。闭包
Add(1)(2)(3)
有....有....有那味了....这....这不就是柯里化吗....函数
有些小朋友可能没有听过,对于大朋友而言耳熟能详,融会贯通。spa
咱们仍是来介绍一下。设计
在《javascript高级程序设计》这本书中有以下介绍:
与函数绑定紧密相关的主题是函数柯里化,它用于建立已经设置好的一个或者多个参数的函数。函数柯里化的基本方法和函数绑定是同样的:使用一个闭包返回一个函数。二者的区别在于,当函数被调用时,返回的函数还须要设置一些传入的参数。
咱们来写写看:
function Add(x) { return function (y) { return return functio (z) { return x + y + z; } } } // 简洁写法 const Add = x => y => z => x+y+z;
执行一下
Add(1)(2)(3) // 6
是咱们要的那味~
那么咱们既然已经写出了这个形态,咱们就一步一步反推。
这个时候千万别紧张,咱们从最低级的形态出发,写出一个最基本的形态,可以有效地帮助咱们创建自信心,吃下定心丸,按照这种方式,哪怕咱们最终没有写出完美的结果,让面试官看到你思考解题的过程,也是一种加分。
好,接着说~
那咱们接下来须要实现这个样子。
Add(1,2,...)(3)(4)
传入参数不止一个
咱们知道,对于不肯定参数个数,咱们能够使用 arguments
这个对象来获取到全部的入参,可是 arguments
不是一个 Array
,可是咱们能够使用 ES6 中的 Spread syntax (展开语法)去将他变成一个数组。表演继续。
function Add() { const nums = [...arguments]; return function() { nums.push(...arguments); return function() { nums.push(...arguments); return nums.reduce((a, b) => a + b); } } }
nice!已经离咱们最终的形态愈来愈近了。接下来是这个函数可以无限的进行调用。
Add(1,2,...)(3)(4)(...)
那么怎么样才能无限调用呢?没错,用递归。
function Add() { const nums = [...arguments]; function AddPro() { nums.push(...arguments); return AddPro; } return AddPro; }
嗯,其实咱们写到这里发现了... 因为是无限递归,咱们没办法肯定最后一次函数调用,所以咱们须要最后显式调用一个结束的方法来打印出最后的数据。
很天然地,咱们能够在 AddPro
添加一个方法 sumOf
来解决这个问题。
学弟就是卡在这里地方,被函数添加上一个方法搞懵了。你是否知道呢?
function Add() { const nums = [...arguments]; function AddPro() { nums.push(...arguments); return AddPro; } AddPro.sumOf = () => { return nums.reduce((a, b) => a + b); } return AddPro; }
好啦好啦,结束啦。
等等
在最后,我再来补充一种方案,function
不只能够继续挂载 function
~ 还能够挂载变量哦~
function Add() { if (!Add.nums) { Add.nums = []; } Add.nums.push(...arguments); return Add; } Add.sumOf = () => { return Add.nums.reduce((a, b) => a + b); }
若是上述回答有更优解,请公众号后台回复,留下你的微信,红包相送。
咱们总结一下,小小的面试题涉及到的基础知识。
闭包、递归、做用域、函数与对象
基础就是基础,永远是你爸爸,掌握好基础,以不变应万变。
function Add() { const nums = [...arguments]; return () => { nums.push(...arguments); return () => { nums.push(...arguments); return nums.reduce((a, b) => a + b); } } } // 若是我上述代码中间换成箭头函数又会怎么样呢~
也许你以为这题有点简单,经过简单的重复练习就能轻松记住,可是最主要的是思路,不少事情都是同样,掌握事情的方法和方向是最重要的。毕竟淘宝也不是一蹴而就的~ 可是只要方向正确了,都会好起来的。
若是个人文章有帮助到你,但愿你也能帮助我,欢迎关注个人微信公众号 秋风的笔记
,回复好友
二次,可加微信而且加入交流群,秋风的笔记
将一直陪伴你的左右。