这里有一个很基本的函数:
function box(val){
console.log('假设这是函数原有代码');
val(); //这是回调函数
}
现在控制台运行它的结果是这样的:
box(function(){console.log('回调函数 01')}); //返回 [假设这是函数原有代码] + [回调函数 01 ]
box(function(){console.log('回调函数 02')}); //返回 [假设这是函数原有代码] + [回调函数 02 ]
很正常,上一次的结果被这次的参数替代掉了
现在要达到的需求:
box(function(){console.log('回调函数 01')}); //返回 [假设这是函数原有代码] + [回调函数 01 ]
box(function(){console.log('回调函数 02')}); //返回 [假设这是函数原有代码] + [回调函数 01 ] + [回调函数 02 ]
说简单点就是:如何在一个函数内追加新的代码片段,更新这个 box 函数,还不能执行它(它也是回调函数,有条件才能激活的) 请问该如何做到,如果有懂得 v 友,还希望不要吝啬赐教。
1
krixaar 2020-08-06 08:57:54 +08:00 1
没看明白,你为啥不能传个存了一堆不同函数的数组进去一个个跑?
|
2
mostkia OP @krixaar 因为传入函数是随机的,不是预置在内部的,否则就好处理了😂而且可能随时增加新的函数进去,怎么说呢,有点类似于这个吧 window.addEventListener,写入了一个回调,再次写入一个新的,不会覆盖上次的代码。
|
3
kop1989 2020-08-06 09:07:12 +08:00 2
首先,这个需求不符合代码设计逻辑,典型的腐败代码。
理论上讲,一个 function,输入相同的参数,输出也应该是固定逻辑的。值不一定相同,但是逻辑处理要稳定。 其次,如果这个需求描述正确的话: 1 、box 是否能改?如果能改则可以传递 function 的数组解决。 2 、如果 box 不能改,则从回调函数入手,你可以把逻辑累加这个过程放在 box 外面维护。 |
4
yaphets666 2020-08-06 09:08:49 +08:00 2
function(...arg) {
arg.forEach(item=>{ item() }) } |
5
en20 2020-08-06 09:08:55 +08:00 via iPhone 1
加个参数 eval 一下?
|
6
hoythan 2020-08-06 09:09:29 +08:00 1
他的意思明显就是想要实现 php 的 filter 和 action 功能。
|
7
journey0ad 2020-08-06 09:10:14 +08:00 via iPhone 1
闭包+数组
|
8
ccraohng 2020-08-06 09:10:44 +08:00 via Android 1
看起来是要把以前传入的也保留?
顶层用一个数组,每次传入保存进去,返回所有数组的执行结果 |
9
tyx1703 2020-08-06 09:12:38 +08:00 1
闭包可解
const box = (() => { const callbacks = []; return (callback)=> { if (callback instanceof Function) { callbacks.push(callback); return; } callbacks.forEach(callback => { callback(); }); } })(); |
10
ianva 2020-08-06 09:23:55 +08:00 3
``` javascript
const box = (() => { const callbackList = []; return callback => { callbackList.push(callback); callbackList.forEach(item => item()); }; })(); ``` |
11
mostkia OP @kop1989 是的,我也感觉不太符合正常的代码逻辑,不过具体项目只有我最清楚,关于这方面我会仔细考虑的,感谢你的意见。
@en20 @journey0ad @ccraohng @tyx1703 看来意见是出奇的一致,我朝这个方向研究一下,我一开始也感觉闭包可以做到,但以往都是传递保留数据,没试过函数,一下子不知道该从何入手。 感谢诸位出谋划策,不一一 @了,已发感谢~ |
12
cin 2020-08-06 09:29:55 +08:00 1
var box = val => {
const fn0 = () => { console.log('假设这是函数原有代码') } const fns = [fn0] box = fn => { fns.push(fn) fns.forEach(fn => fn()) } box(val) } |
13
azcvcza 2020-08-06 09:30:19 +08:00 1
要存东西,里面的状态要独立,且可更新,在 js 里就只能用闭包了
|
14
ianva 2020-08-06 09:31:17 +08:00
JavaScript 这个语言就闭包这一个特性能拿的出手吧,其他都是点缀,还是要多了解
|
16
cyrbuzz 2020-08-06 09:55:48 +08:00
在更进一步,数组外层再用一个对象(可以用 weakMap 不会造成垃圾回收的负担额)包裹。
|
17
liberty1900 2020-08-06 10:02:33 +08:00 1
这个就是简单的 memorization, 写过 react 或者尝试过函数式编程应该都知道
都说在 JS 里函数是第一公民,其实意思是函数就和普通变量一样,但实际函数可以做的更多,实际上应该是特等公民 |
19
stillsilly 2020-08-06 10:09:15 +08:00 1
用装饰者模式
运行结果截图: https://i.loli.net/2020/08/06/UlrdQPqua1sCiDK.png 代码: function box(){ console.log('假设这是函数原有代码'); } function 装饰 box(){ var _box = box function 新加的函数(){ console.log('这是新加的函数') } box = function (){ _box() 新加的函数() } } 装饰 box() box() |
20
libook 2020-08-06 10:29:29 +08:00 1
基本思路就是在这个函数能被调用的整个生命周期里,开辟一个存储空间来存每次传入的 callback,然后每次调用这个函数都从这个存储空间里读出之前所有传入过的 callback 一起调用。
上面楼层都给出了实际的代码。 有一个问题需要注意,就是你开辟的存储空间是有限的,在长时间高频调用的情况下,理论上有可能达到上限而抛出错误,而且因为每次执行的函数数量递增,执行需要的计算量和时长也会逐渐增加。 从代码可读性上,可以调整代码结构或增加注释来让看代码的人很快意识到这个函数的特殊性。 比如可以创建一个 Class,实例化的对象的状态保存在对象内部,通过调用对象的方法来实现你的功能。 |
21
ianva 2020-08-06 11:00:42 +08:00
也可以做一个 curry factory,对这一类问题做处理
const curryFactory = fn => { __const list = []; __return (...args) => { ____if (args.length) { ______console.log(args); ______list.push(...args); ____} else { ______return fn(...list); ____} __}; }; 全部源码,https://codesandbox.io/s/elated-cartwright-szp2w |
22
ianva 2020-08-06 11:01:36 +08:00 1
const box1 = curryFactory((...args) => {
__Array.from(args).forEach(item => item()); }) box1(() => { __console.log("1"); }); box1(() => { __console.log("2"); }); box1(); |
23
ianva 2020-08-06 11:10:59 +08:00
@wellsc 并不是一个好的特性,特别是当年 for in 的时候还会把原型方法遍历出来,必须 hasOwnProperty,所以大部分的库都不会选择轻易的通过原型方法做入侵
|
26
mostkia OP 好的,感谢诸位,不一一 @了浪费大家时间了,有意义的回复均已感谢~
|
27
catch 2020-08-06 13:13:08 +08:00 via iPhone
我看了你最近问的两个问题,标题都写的很奇怪,实则就都很基础的 js
|
28
mostkia OP @catch emm 。。怎么说呢,你说的的确有道理,比如像我之前的一个问题。其实吧,我提问的主要动机,主要是不知道一些偏门的需求自己这样闭门造车实现出来,代码是不是走偏了,发出来看看大家是怎么解决的,笨办法都是有的,但有最优解我肯定是想要了解一下的,看到大家都是这样做的,一般也就没差了。
|
29
Exceptionluo 2020-08-07 09:48:15 +08:00 1
|
30
mostkia OP @Exceptionluo 好的,有效,感谢
|