一道经典的JavaScript面试题(转)

前两天一位朋友发邮件问了我关于这道经典的面试题,其实在这位朋友给我发邮件之前曾经也有人给我发过邮件询问过此类笔试题,思前想后觉得写出来给那些还正在解答此题中的朋友们。
题的原型:
var add = function (m) {
 
    var temp = function (n) {
        return add(m + n);
    }
 
    temp.toString = function () {
        return m;
    }
 
    return temp;
};
add(3)(4)(5); // 12
add(3)(6)(9)(25); // 43
 
这个add函数可以无限次调用循环调用,并且把所有传进去的值相加,最后返回相加总数。这道题咋一看有点特别,但代码量极其少而精,重点技术在于:作用域、交替、匿名函数、toString的巧妙。
让我们来解释这个过程:add(3)(4)(5)
1、先执行add(3),此时m=3,并且返回temp函数;
2、执行temp(4),这个函数内执行add(m+n),n是此次传进来的数值4,m值还是上一步中的3,所以add(m+n)=add(3+4)=add(7),此时m=7,并且返回temp函数
3、执行temp(5),这个函数内执行add(m+n),n是此次传进来的数值5,m值还是上一步中的7,所以add(m+n)=add(7+5)=add(12),此时m=12,并且返回temp函数
4、关键性一步来了,后面没有传入参数,等于返回的temp函数不被执行而是打印,了解JS的朋友都知道对象的toString是修改对象转换字符串的方法,因此代码中temp函数的toString函数return m值,而m值是最后一步执行函数时的值m=12,所以返回值是12。
看到这其实就很明白了,代码中temp.toString的重写只是为了函数不执行时能够返回最后运算的结果值,所以这个地方是可以任意修改的,你让它返回什么它就返回什么,比如改写:
temp.toString = function () {
    return "total : " + m;
}
执行结果:
>>> add(3)(4)(5);
total : 12
#前端工程师#
全部评论
其实。。。就是函数柯里化curry,另外取值是调用valueOf,valueOf调用toString,所以改valueOf可以少一步 function curry(fn) { let result = 0 const _fn = function () { result += fn.apply(this, arguments) return _fn } _fn.valueOf = function() { const temp = result result = 0 return temp } return _fn } function add() { return Array.prototype.reduce.call(arguments, function(p, v) { return p + v }, 0) } add = curry(add) add(2,3,4)(2)(3) === 14 这个是不定参数的,最后结果是数字,这个还有很多变种。。。参数固定的话可以把result改成数组,每次调用就push进去,最后取值时全部塞到被curry的函数里。具体实现有很多。可以一一尝试
点赞 回复 分享
发布于 2016-09-18 23:20
可以可以  感谢分享
点赞 回复 分享
发布于 2016-09-18 22:12
点赞 回复 分享
发布于 2016-03-15 10:49

相关推荐

虾皮前端一面总结一、八股文考察1. 箭头函数◦ 核心问题:需明确箭头函数特性(无this、arguments、prototype,不能用new)。◦ 未答关键点:◦ this继承自外层词法作用域,非构造函数因无prototype且new时无法绑定this。◦ new过程需创建实例、绑定this、返回实例,箭头函数无[[Construct]]内部方法。2. 性能优化◦ 问题:不熟悉相关知识,需补充学习(如防抖节流、SSR、CDN、懒加载等)。3. 浏览器内存与缓存◦ Local/Session Storage:数据存储于磁盘,读取时从内存缓存或磁盘获取(取决于是否常驻内存)。◦ 协商缓存:◦ max-age=0与no-cache区别:前者强制验证缓存,后者需服务器确认。◦ ETag与Last-Modified并存:前者更精准(文件内容变化),后者依赖时间戳(可能误判)。4. React Hook◦ 问题:对useMemo、useCallback、memo使用场景模糊。◦ 改进点:结合项目举例(如子组件高频渲染时用memo缓存,避免函数重复创建导致的重渲染)。二、代码题• 动态规划背包问题:用最少砝码数量组合目标重量,需明确状态转移方程(如dp[i] = min(dp[i], dp[i - w] + 1))。三、面试官交流1. AI看法:强调合理利用AI辅助解决复杂问题,提升效率。2. 性能优化建议:结合具体场景(如电商首屏优化、可视化图表性能),参考谷歌Lighthouse、Web Vitals等工具。四、改进方向1. 基础巩固:深入理解箭头函数原理、浏览器存储机制、HTTP缓存策略。2. 性能专题:系统学习优化手段,结合实际项目案例分析。3. React实践:梳理Hook使用场景,通过项目练习巩固(如列表渲染优化)。4. 算法训练:强化动态规划题型,掌握背包问题变种解法。
点赞 评论 收藏
分享
评论
4
22
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务