关于add(2)(3)(4)的记录
来源:互联网 发布:js判断哪个tr被双击 编辑:程序博客网 时间:2024/05/28 19:23
最近在读汤姆大叔的系列博文,看到这样一道题,记录下解题过程
题目:实现如下语法的功能:var a = add(2)(3)(4); //9
很显然,要通过闭包来保存中间计算的结果,并通过返回函数进行级联操作,这个返回的函数还应该是一个自引用函数。
由于之前在别的地方看到过类似的题目,记得同时要求满足add(2,3)(4)这样的调用,于是做了下处理。
I
let add = function() { let args = []; return function add() { args = [...args, ...arguments]; console.log( args.reduce((a,b) => a+b) ); return add; }}();
能运行,同时满足两种调用方式。
但是发现因为这是个IIFE,只初始化了一份,多次调用的结果是累计的。
IIfunction add2() { let args = []; return function add() { args = [...args, ...arguments]; console.log(args.reduce((a,b) => { console.log(`${a} + ${b} = ${a+b}`); return a+b })); return add; }(...arguments)}a = add2(2)(3)(4);b = add2(2,3)(4);
去掉IIFE,每次第一次调用才生成一个新的闭包,可以生成多个实例。
但是通过打印发现,每次级联调用,存在重复计算,
即其实可以只保留上次的运行结果,而不是每次都从头开始计算
III
function add3() { let args = []; return function add() { args = [ [...args, ...arguments].reduce((a,b) => {console.log(`${a} + ${b} = ${a+b}`);return a+b }) ]; console.log(args); return add; }(...arguments)}a = add3(2)(3)(4);b = add3(2,3)(4);
按照上述的改进,改变了下储存的值,从而减少了计算。
考虑到最近在看设计模式,要求职责分离。
确实可以将add的功能剥离出来,之后如果要求做一个sub(100,20)(30),就可以直接重用了。
IV
function cascade(deal) { return function() { let args = []; return function fn() { args = [ deal(...args, ...arguments) ]; console.log(args); return fn; }(...arguments) }}
分离后的cascade接收一个处理业务的回调,这样分离后,感觉重用性好了些。
到这里想不到什么优化点了,于是搜了下其他网友的实现,发现大同小异,但是我忽略了一点:现在的函数结果必须返回一个函数用于级联调用,那么如何获取每次操作的结果呢?
网友的选择是重写了valueOf和toString方法,这样也可以,但是感觉没必要到要重写的地步。
V
function cascade(deal, name) { name = name || 'res'; return function() { let args = []; return function fn() { args = [ fn[name] = deal(...args, ...arguments) ]; console.log(fn[name]); return fn; }(...arguments) }}let add4 = cascade(function() { return [...arguments].reduce((a,b) => { console.log(`${a} + ${b} = ${a+b}`); return a+b });});
可以直接在返回的这个自引用函数上挂一个属性来保存每次的操作结果。
最终代码整理成es5,如下
function cascade(deal, name) { name = name || 'res'; return function() { var args = []; return function fn() { for (var i = 0; i < arguments.length; ++i) { args.push(arguments[i]); } args = [ fn[name] = deal.apply(null, args) ]; return fn; }.apply(null, arguments) }}var add = cascade(function() { var res = arguments[0]; for (var i = 1; i < arguments.length; ++i) { res = res + arguments[i]; } return res;});
阅读全文
0 0
- 关于add(2)(3)(4)的记录
- 关于add和Floodfill的记录
- 关于Xcode5,4,3版本间的Add Headers
- 关于ListIterator.add() 的翻译
- 实现1.add(1).add(2).add(3)……的级联叠加
- 关于TextBox1.Attributes.Add的问题
- 关于arrayList的add和addall
- 关于ArrayList.add方法的问题
- 关于arrayList的add和addall
- Django 关于manytomany add的问题
- 关于网上商城开发的随笔记录4
- 关于网上商城开发的随笔记录2
- 关于调色板的记录
- 关于Canvas的记录
- 数据不变,修改行记录标志为add的方法
- javascript add(1)(2)(3)(4)解析
- javascript add(1)(2)(3)(4)解析
- LeetCode习题记录(2)Add Two Numbers
- js比较器组件Comparator.js
- interleaving-string
- Python初学笔记-io流和异常
- Dragon of Loowater UVA
- 自练题20170801
- 关于add(2)(3)(4)的记录
- codeforces 812E
- 蓝桥杯 数列排序
- JAVA_Web知识体系(浅入浅出)
- hihocoder1586-2017acm北京网络赛9&线段树&思维&板子- Minimum
- 用线段树求解坐标矩阵中的交并集面积思路及其模板代码
- python--leetcode557. Reverse Words in a String III
- 数值的整数次方
- 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛:Frequent Subsets Problem