我在看别人代码的时候,有看到代码是这样写的
function(){ fn&&fn() }
大概意思是这么个意思,但是这我感觉这样写好像没意义,有带佬能指点一下吗
1 VWMMWV OP 要是 fn 不存在那肯定会直接报错 fn undefined ;要是 fn 存在;那直接执行 fn() 就好了 |
![]() | 2 szq8014 2020-06-23 11:56:00 +08:00 只有有 fn 这个变量的时候才会当成函数执行,否则不执行,console 就不会报错了? |
3 cjc2017 2020-06-23 11:56:03 +08:00 ![]() 自抛自扣?? |
![]() | 4 dumbass 2020-06-23 11:56:45 +08:00 处理回调 |
5 seeker 2020-06-23 11:56:59 +08:00 ![]() if (fn) { fn() } |
![]() | 6 Perry 2020-06-23 12:01:41 +08:00 大部分情况是 1 楼这个意思,如果 fn 是 undefined 就不执行 fn()。React 针对 optional callback 会这么写。 |
8 ochatokori 2020-06-23 12:24:17 +08:00 via Android @VWMMWV #1 错了,fn 不存在就什么都不做,不会报错,fn 存在才尝试执行 fn |
![]() | 9 rioshikelong121 2020-06-23 12:29:46 +08:00 短路。另外不会报错。 |
![]() | 10 shenyu1996 2020-06-23 12:30:33 +08:00 if (fn) { fn() } |
![]() | 11 shenyu1996 2020-06-23 12:32:04 +08:00 没注意和 5 楼重复了 用 if 语句就更好理解了吧 |
12 dremy 2020-06-23 12:37:43 +08:00 via iPhone 这种不标准的写法完全是负分,竟然还有人用来装 B… |
![]() | 13 xiangyuecn 2020-06-23 12:41:22 +08:00 ![]() @dremy #12 在 js 里面,这是标准的。大幅减少代码量,比三目运算更直接了当。别的语言大同小异:fn?.xx() |
15 dremy 2020-06-23 12:50:30 +08:00 @xiangyuecn 大幅减少代码量?可读性的下降之后,代码量的减少有意义吗?这分明是不能区分判断语句和条件表达式的区别导致的 与其: abc && fn && fn(abc) 不如: if (abc && fn) { fn(abc) } |
![]() | 17 chiu 2020-06-23 12:54:54 +08:00 短路, bash 里常见 |
![]() | 18 northernlights 2020-06-23 13:00:20 +08:00 不会报错,fn 即!!fn 。这个写法通常在回调里用。有 fn 就执行 fn |
![]() | 20 xiangyuecn 2020-06-23 13:02:31 +08:00 @dremy #15 比三目运算更直接了当:可读性更好的意思 |
![]() | 21 Vogan 2020-06-23 13:03:51 +08:00 @dremy 你那是 jsx 。在调用 props 的函数的时候,很正常。this.props.cb && this.props.cb() |
![]() | 22 taxiaohaohhh 2020-06-23 13:04:43 +08:00 @dremy 负分哪里得出的,还有这个写法怎么装逼的 |
![]() | 23 xiangyuecn 2020-06-23 13:06:41 +08:00 很多古董语言开始没有简写的 null 判断,一堆 if else,非常难看,后面陆续都有了可空类型,普遍简写成一句话,类似:nullObj?.call(),还是 js 的语义上更直白 obj&&obj.call() |
![]() | 24 Vegetable 2020-06-23 13:06:43 +08:00 就是一个 or 运算符,前者为 true,再判断后者,否则就直接 false 。 其实不推荐这种写法,本身这个写法其实很易懂了,楼主还是没直接理解。 这种东西拜托不要写在业务代码里。 |
25 dremy 2020-06-23 13:08:41 +08:00 @Vogan @taxiaohaohhh 见 https://eslint.org/docs/rules/no-unused-expressions Expected an assignment or function call and instead saw an expression. |
26 nianyu 2020-06-23 13:15:18 +08:00 如果存在 fn 就执行 fn, 正常业务代码这么写的比较少 |
![]() | 27 xiangyuecn 2020-06-23 13:18:31 +08:00 @nianyu 就算你不手写,打包后人家自动帮你改成这个格式 源码:function aa(fn){ if(fn)fn() } UglifyJS ( webpack ) 压缩:function aa(t){t&&t()} |
![]() | 28 no1xsyzy 2020-06-23 13:22:19 +08:00 @dremy #25 首先,你搞错了,这个问题不是 no-unused-expressions 。 其次,eslint 是可配置的。 |
29 ChanKc 2020-06-23 13:22:46 +08:00 via Android ![]() 果然出现了 js 一大争议:是否手动 minify 根源上是“程序主要是给人读的”还是“程序主要是给机器读的”的争议 |
![]() | 30 nannanziyu 2020-06-23 13:23:08 +08:00 |
31 ChanKc 2020-06-23 13:25:33 +08:00 via Android 换我我就写 typeof fn === 'function' |
![]() | 32 lemon6 2020-06-23 13:27:27 +08:00 via Android 短路写法啊,减少代码量,而且就这么一点东西哪有降低可读性一说? |
33 zhuweiyou 2020-06-23 13:29:53 +08:00 ![]() 这样写是错误的,应该 typeof fn === "function" |
![]() | 34 marcong95 2020-06-23 13:30:23 +08:00 ![]() @dremy #25 这只是 ESLint 的一个规则,并不代表这种写法不被提倡,何况你这个规则也并不在 eslint:recommended 里面 JS 里面大量需要判断函数非空,要是都 if 一下只会把代码弄得又长又臭 |
![]() | 36 binux 2020-06-23 13:31:26 +08:00 via Android @nannanziyu #29 你还得判断它是不是一个异步函数,再捕获它的异常。 |
37 ChanKc 2020-06-23 13:34:16 +08:00 真要减少代码量就上 ts 这检查还检查得不彻底 |
![]() | 39 lizz666 2020-06-23 13:45:24 +08:00 你未来还会看到类似 window?.fb?.() 的 |
![]() | 40 icanfork 2020-06-23 13:47:20 +08:00 这样写思路是对的,实现是错误的,fn 可能存在,但是它可能不是 function,执行 fn() 一样会出错。 typeof fn === "function" && fn() |
![]() | 41 taxiaohaohhh 2020-06-23 13:47:25 +08:00 @nannanziyu 就我回复的层主,{fn ? fn(abc) : null},你要讲没判断是否是函数负分,if 能加难道我这个加不了? |
42 ChanKc 2020-06-23 13:49:38 +08:00 ![]() 用一个很流行的词来说这个代码:心智负担 要彻底看懂这个代码,需 1 完全记住 js 的自动类型转换规则 2 记住 0, NaN, null, undefined, ''是 falsy 的值,其它都是 truthy 的 而且以上两条基本要靠死记硬背,没什么规律可言 基本上偏学术性的编程书都不推荐这个写法 偏工程的就有一些推荐的,原因就只有减少代码量 |
![]() | 43 marcong95 2020-06-23 13:50:29 +08:00 @dremy #38 那么问题来了,单纯的 fn() 是语句呢,还是表达式呢?那说 new Vue({ ... }) 呢 |
![]() | 44 Marstin 2020-06-23 13:51:27 +08:00 如果按照楼上的众多反对说法,三元表达式和 lambda 表达式都应该取缔。 避免因程序报错中断因而影响后续逻辑的继续执行,这种短路用法不是很实用吗 |
![]() | 45 starcraft 2020-06-23 13:54:13 +08:00 via iPhone 哈哈哈 还有人说这是装笔的。这是对得不能再对的做法了。果真无知才是最装笔的。评论区依旧没让人失望。 |
46 slxyzzl 2020-06-23 14:06:45 +08:00 我想问业务代码这么写有什么问题,老项目我们全是这样写的,新项目换成可选链了 |
47 iiqiu 2020-06-23 14:06:58 +08:00 ![]() fn?.() |
48 lscho 2020-06-23 14:09:16 +08:00 ![]() 难道我这么多年 js 白写了吗?这难道不是回调函数时正常的写法? 也不需要 typeof fn === "function" 判断,因为期望参数 fn 是函数,如果不是,那就应该抛出异常。 |
![]() | 49 no1xsyzy 2020-06-23 14:10:55 +08:00 @dremy #25 又翻了一下只看到 no-unneeded-ternary 里面 Good 例子用到了 bar || 1 而 fn && fn() 是 lint-free 的,即使钩上所有 rule ( ES2016 + browser ) 大概需要避免 fn && fn() 需要自己写扩展 document.write(((fn) => { "use strict"; return fn && fn(); })()); |
![]() | 51 IGJacklove 2020-06-23 14:16:12 +08:00 via Android @dremy 也不会把,现在 ts 都有?. 和??各种操作了,要是都 if 判空不得累死你? |
![]() | 53 xcatliu 2020-06-23 14:42:59 +08:00 ![]() @dremy 你怕是没读过 React 官方文档吧。React 的标准写法分明是 <div>fn && fn(abc)</div> https://reactjs.org/docs/conditional-rendering.html#inline-if-with-logical--operator ![]() |
55 whileFalse 2020-06-23 15:06:08 +08:00 @dremy 这种写法出现的时候你大概还不会写程序。 |
![]() | 56 Sapp 2020-06-23 15:06:09 +08:00 现在用这个:fn?.() |
![]() | 57 zhjie 2020-06-23 15:07:21 +08:00 对于 js 来说 这么写基本没有心智负担。甚至面试都会提问。 |
![]() | 58 maichael 2020-06-23 15:09:20 +08:00 @ChanKc #33 上 TS 也解决不了这问题,你不能担保调用你这个函数的人也用的 TS,而且也存在 fn 可以为空的情况。 |
59 goodboy95 2020-06-23 15:12:34 +08:00 @ChanKc js 里面记住非 true 的情况感觉是基本吧,而且这个明显就是只为了回避 null 和 undefined. 这都有心智负担的话,我只能怀疑拿到代码的人以前根本就没碰过 js,临时被拉去维护 js 项目。只要是写 js 吃饭的,这种代码应该都是瞄一眼就过去的事情。 |
60 Jirajine 2020-06-23 15:13:13 +08:00 via Android 这个就是 js 逻辑运算符的魔法: 当多个 &&串联时,执行到第一个 truthy 的表达式; 当多个||串联时,执行到第一个 false-thy 的表达式; 但我比较赞同王垠博客上的观点:短路机制是给程序优化执行效率的,不是给程序员拿来炫技的。 |
61 ChanKc 2020-06-23 15:14:16 +08:00 via Android @maichael 如果是完全内部使用的函数,ts 可以解决问题。我刚刚在 playground 上试了一下,指定 fn 为 Function 类型,如果 fn 是空就会编译错误。如果是对外的函数,这个判断也需要假设用户传入的要么是 falsy 的值要么是函数。那么为什么不干脆假设用户传入的就是个函数? |
![]() | 62 maichael 2020-06-23 15:18:25 +08:00 @ChanKc #57 因为你没法这么假设,需求完全可能是 fn 的类型是 Function | undefined,这是需求层面决定的,传了我就执行,不传我就不执行,这是很正常的需求。 |
63 ChanKc 2020-06-23 15:18:49 +08:00 via Android @goodboy95 Cay S Horstman 就觉得这个不是基本的。Douglas Crockford 也建议“Use booleans in all conditions” |
64 ChanKc 2020-06-23 15:20:21 +08:00 via Android @maichael 如果需求是这样,显式的===undefined 然后让 minifier 去 minify 不好吗 |
65 ChanKc 2020-06-23 15:25:37 +08:00 via Android @goodboy95 要达到你这个要求,你就要在招聘的时候让每个应聘者背出 falsy 的值,确保不会有别的团队写 c 的写 java 的调岗到你的团队,然后你才可以放心地使用各种 truthy 和 falsy 的 hack 而保证不出错 |
![]() | 66 no1xsyzy 2020-06-23 15:47:28 +08:00 |
![]() | 67 dumbass 2020-06-23 15:49:36 +08:00 这也能吵起来。。。 |
68 ChanKc 2020-06-23 15:55:31 +08:00 via Android @no1xsyzy 我当然猜得到,问题根本不在短路,而是在强制类型转换。JS 的强制类型转换规则对别的语言的程序员来说是很奇葩的 |
![]() | 69 no1xsyzy 2020-06-23 16:00:49 +08:00 @ChanKc #68 慢点这里没有强制类型转换啊,你说的是隐式类型转换的话,Python 、C 、Java 等等一大堆都有任何东西当作布尔的倾向,以至于 codegolf meta 那边专门提出 “如果要返回 True/False 的话 Truthy 和 Falsy 是否可以直接用”,最后提出能塞进分支判断直接当 True/False 用的都算(因为是 Code Golf 所以需要进行社区约定) 自然,三位一体本身倒是让人难受,但 T/F 我觉得还不至于,总比 't 和 nil 是标准形态好多了。 |
71 Jirajine 2020-06-23 16:07:58 +08:00 via Android @no1xsyzy 没有反,&&遇到 true 就短路所以是执行到第一个 truethy 的表达式后停止,当然这里说执行不准确应该是 evaluate 。 不是我秀英文,这个词我中文表示出来。而且这俩本来就是词典里没有的生造词,忘了别人怎么写的了我就随手打出来,能表达清意思就够了,论坛回帖又不是写论文,何必咬文嚼字。 |
![]() | 73 AV1 2020-06-23 16:25:58 +08:00 ![]() 请用最新写法 [fn?.()] ,更简单易读,其他的都别争了,省点口水吧。 |
![]() | 76 AV1 2020-06-23 16:51:29 +08:00 @progerchai 就是?.操作符,不包括方括号,我把引号打成方括号了。 可以参见这里: https://developer.mozilla.org/en-US/docs/Web/Javascript/Reference/Operators/Optional_chaining |
![]() | 77 ke1vin 2020-06-23 17:27:04 +08:00 不用判断类型? |
![]() | 80 no1xsyzy 2020-06-23 18:07:51 +08:00 @Jirajine #71 提问: 1 && 2 && 3 && 4 = ? null || undefined || 0 || "" = ? && 是遇到 false 短路啊,遇到 true 继续,不然怎么是 if(a){b} 呢 |
![]() | 82 iamppz 2020-06-23 19:19:57 +08:00 via iPhone js 不这么写,ts 会这么写,因为类型检查有编译器处理 |
84 Jirajine 2020-06-23 20:05:13 +08:00 @no1xsyzy #80 好吧是我弄反了,自己印证了上面的观点:尽量避免这么用。 回帖搞反顶多被网友批判一番,关键业务逻辑搞反造成重大损失可能就得跑路了。 |
![]() | 86 auroraccc 2020-06-23 20:28:01 +08:00 a && a.b && a.b.c && a.b.c() a?.b?.c |
![]() | 87 cigarzh 2020-06-23 21:48:12 +08:00 函数式编程基操 不要用面向对象的思想思考函数式编程的玩意… |
88 royzxq 2020-06-24 00:10:11 +08:00 偷懒的时候会这么写 |
89 back0893 2020-06-24 00:15:31 +08:00 有 fn 就执行 灭有就不执行 不是很常规的写法 |
![]() | 91 fuwu1245 2020-06-24 10:08:04 +08:00 如果 fn 不是函数呢?那 fn()不就是个错了么 |
![]() | 92 donghui1993 2020-07-28 14:00:56 +08:00 正确写法应该时这个吧:typeof(fn)==='function' && fn(),不过通常约定 fn&&fn() 传递的一定是函数 |