V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
VWMMWV
V2EX  ›  JavaScript

在 JS 中存在 "fn && fn() " 执行语句 这个语句有什么意义吗?

  •  1
     
  •   VWMMWV · 2020-06-23 11:53:46 +08:00 · 8680 次点击
    这是一个创建于 1613 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我在看别人代码的时候,有看到代码是这样写的

    function(){
      fn&&fn()
    }
    

    大概意思是这么个意思,但是这我感觉这样写好像没意义,有带佬能指点一下吗

    92 条回复    2020-07-28 14:00:56 +08:00
    VWMMWV
        1
    VWMMWV  
    OP
       2020-06-23 11:55:31 +08:00
    要是 fn 不存在那肯定会直接报错 fn undefined ;要是 fn 存在;那直接执行 fn() 就好了
    szq8014
        2
    szq8014  
       2020-06-23 11:56:00 +08:00
    只有有 fn 这个变量的时候才会当成函数执行,否则不执行,console 就不会报错了?
    cjc2017
        3
    cjc2017  
       2020-06-23 11:56:03 +08:00   ❤️ 2
    自抛自扣??
    bojackhorseman
        4
    bojackhorseman  
       2020-06-23 11:56:45 +08:00
    处理回调
    seeker
        5
    seeker  
       2020-06-23 11:56:59 +08:00   ❤️ 3
    if (fn) {
    fn()
    }
    Perry
        6
    Perry  
       2020-06-23 12:01:41 +08:00
    大部分情况是 1 楼这个意思,如果 fn 是 undefined 就不执行 fn()。React 针对 optional callback 会这么写。
    VWMMWV
        7
    VWMMWV  
    OP
       2020-06-23 12:11:57 +08:00
    @seeker ok
    ochatokori
        8
    ochatokori  
       2020-06-23 12:24:17 +08:00 via Android
    @VWMMWV #1 错了,fn 不存在就什么都不做,不会报错,fn 存在才尝试执行 fn
    rioshikelong121
        9
    rioshikelong121  
       2020-06-23 12:29:46 +08:00
    短路。另外不会报错。
    shenyu1996
        10
    shenyu1996  
       2020-06-23 12:30:33 +08:00
    if (fn) {
    fn()
    }
    shenyu1996
        11
    shenyu1996  
       2020-06-23 12:32:04 +08:00
    没注意和 5 楼重复了 用 if 语句就更好理解了吧
    dremy
        12
    dremy  
       2020-06-23 12:37:43 +08:00 via iPhone
    这种不标准的写法完全是负分,竟然还有人用来装 B…
    xiangyuecn
        13
    xiangyuecn  
       2020-06-23 12:41:22 +08:00   ❤️ 3
    @dremy #12 在 js 里面,这是标准的。大幅减少代码量,比三目运算更直接了当。别的语言大同小异:fn?.xx()
    Perry
        14
    Perry  
       2020-06-23 12:42:17 +08:00   ❤️ 1
    @dremy 这个扯不上装吧,React 的 JSX 里面经常这么些。
    dremy
        15
    dremy  
       2020-06-23 12:50:30 +08:00
    @xiangyuecn 大幅减少代码量?可读性的下降之后,代码量的减少有意义吗?这分明是不能区分判断语句和条件表达式的区别导致的

    与其:
    abc && fn && fn(abc)

    不如:
    if (abc && fn) {
    fn(abc)
    }
    dremy
        16
    dremy  
       2020-06-23 12:53:48 +08:00
    @Perry React JSX 里面的标准写法应该是这样

    <div>
    {fn ? fn(abc) : null}
    </div>
    chiu
        17
    chiu  
       2020-06-23 12:54:54 +08:00
    短路, bash 里常见
    northernlights
        18
    northernlights  
       2020-06-23 13:00:20 +08:00
    不会报错,fn 即!!fn 。这个写法通常在回调里用。有 fn 就执行 fn
    Perry
        19
    Perry  
       2020-06-23 13:01:57 +08:00
    @dremy 那是你们组的标准不是所有人的标准,fn && fn(abc) 也是可以的
    xiangyuecn
        20
    xiangyuecn  
       2020-06-23 13:02:31 +08:00
    @dremy #15 比三目运算更直接了当:可读性更好的意思😏
    Vogan
        21
    Vogan  
       2020-06-23 13:03:51 +08:00
    @dremy 你那是 jsx 。在调用 props 的函数的时候,很正常。this.props.cb && this.props.cb()
    taxiaohaohhh
        22
    taxiaohaohhh  
       2020-06-23 13:04:43 +08:00
    @dremy 负分哪里得出的,还有这个写法怎么装逼的
    xiangyuecn
        23
    xiangyuecn  
       2020-06-23 13:06:41 +08:00
    很多古董语言开始没有简写的 null 判断,一堆 if else,非常难看,后面陆续都有了可空类型,普遍简写成一句话,类似:nullObj?.call(),还是 js 的语义上更直白 obj&&obj.call()
    Vegetable
        24
    Vegetable  
       2020-06-23 13:06:43 +08:00
    就是一个 or 运算符,前者为 true,再判断后者,否则就直接 false 。
    其实不推荐这种写法,本身这个写法其实很易懂了,楼主还是没直接理解。
    这种东西拜托不要写在业务代码里。
    dremy
        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.
    nianyu
        26
    nianyu  
       2020-06-23 13:15:18 +08:00
    如果存在 fn 就执行 fn, 正常业务代码这么写的比较少
    xiangyuecn
        27
    xiangyuecn  
       2020-06-23 13:18:31 +08:00
    @nianyu 就算你不手写,打包后人家自动帮你改成这个格式😏

    源码:function aa(fn){ if(fn)fn() }

    UglifyJS ( webpack )

    压缩:function aa(t){t&&t()}
    no1xsyzy
        28
    no1xsyzy  
       2020-06-23 13:22:19 +08:00
    @dremy #25 首先,你搞错了,这个问题不是 no-unused-expressions 。
    其次,eslint 是可配置的。
    ChanKc
        29
    ChanKc  
       2020-06-23 13:22:46 +08:00 via Android   ❤️ 1
    果然出现了
    js 一大争议:是否手动 minify
    根源上是“程序主要是给人读的”还是“程序主要是给机器读的”的争议
    nannanziyu
        30
    nannanziyu  
       2020-06-23 13:23:08 +08:00
    @taxiaohaohhh
    负分是因为不能只判断不为空,而要判断 typeof === 'function'
    if(typeof fn === 'function'){
    fn()
    }
    ChanKc
        31
    ChanKc  
       2020-06-23 13:25:33 +08:00 via Android
    换我我就写 typeof fn === 'function'
    lemon6
        32
    lemon6  
       2020-06-23 13:27:27 +08:00 via Android
    短路写法啊,减少代码量,而且就这么一点东西哪有降低可读性一说?
    zhuweiyou
        33
    zhuweiyou  
       2020-06-23 13:29:53 +08:00   ❤️ 1
    这样写是错误的,应该 typeof fn === "function"
    marcong95
        34
    marcong95  
       2020-06-23 13:30:23 +08:00   ❤️ 1
    @dremy #25 这只是 ESLint 的一个规则,并不代表这种写法不被提倡,何况你这个规则也并不在 eslint:recommended 里面

    JS 里面大量需要判断函数非空,要是都 if 一下只会把代码弄得又长又臭
    BrettD
        35
    BrettD  
       2020-06-23 13:31:19 +08:00 via iPhone
    @dremy 这个是非常常见的短路写法呀,怎么会降低可读性呢?
    binux
        36
    binux  
       2020-06-23 13:31:26 +08:00 via Android
    @nannanziyu #29 你还得判断它是不是一个异步函数,再捕获它的异常。
    ChanKc
        37
    ChanKc  
       2020-06-23 13:34:16 +08:00
    真要减少代码量就上 ts
    这检查还检查得不彻底
    dremy
        38
    dremy  
       2020-06-23 13:35:13 +08:00
    @BrettD 对于有代码洁癖的人来说,不能忍:语句就是语句,表达式就是表达式,把表达式当语句就是 zz 不正确
    lizz666
        39
    lizz666  
       2020-06-23 13:45:24 +08:00
    你未来还会看到类似 window?.fb?.() 的
    belin520
        40
    belin520  
       2020-06-23 13:47:20 +08:00
    这样写思路是对的,实现是错误的,fn 可能存在,但是它可能不是 function,执行 fn() 一样会出错。

    typeof fn === "function" && fn()
    taxiaohaohhh
        41
    taxiaohaohhh  
       2020-06-23 13:47:25 +08:00
    @nannanziyu
    就我回复的层主,{fn ? fn(abc) : null},你要讲没判断是否是函数负分,if 能加难道我这个加不了?
    ChanKc
        42
    ChanKc  
       2020-06-23 13:49:38 +08:00   ❤️ 1
    用一个很流行的词来说这个代码:心智负担
    要彻底看懂这个代码,需要
    1 完全记住 js 的自动类型转换规则
    2 记住 0, NaN, null, undefined, ''是 falsy 的值,其它都是 truthy 的

    而且以上两条基本要靠死记硬背,没什么规律可言
    基本上偏学术性的编程书都不推荐这个写法
    偏工程的就有一些推荐的,原因就只有减少代码量
    marcong95
        43
    marcong95  
       2020-06-23 13:50:29 +08:00
    @dremy #38 那么问题来了,单纯的 fn() 是语句呢,还是表达式呢?那说 new Vue({ ... }) 呢
    Marstin
        44
    Marstin  
       2020-06-23 13:51:27 +08:00
    如果按照楼上的众多反对说法,三元表达式和 lambda 表达式都应该取缔。

    避免因程序报错中断因而影响后续逻辑的继续执行,这种短路用法不是很实用吗
    starcraft
        45
    starcraft  
       2020-06-23 13:54:13 +08:00 via iPhone
    哈哈哈 还有人说这是装笔的。这是对得不能再对的做法了。果真无知才是最装笔的。评论区依旧没让人失望。
    slxyzzl
        46
    slxyzzl  
       2020-06-23 14:06:45 +08:00
    我想问业务代码这么写有什么问题,老项目我们全是这样写的,新项目换成可选链了
    ypzhou
        47
    ypzhou  
       2020-06-23 14:06:58 +08:00   ❤️ 1
    fn?.()
    lscho
        48
    lscho  
       2020-06-23 14:09:16 +08:00   ❤️ 8
    难道我这么多年 js 白写了吗?这难道不是回调函数时正常的写法?

    也不需要 typeof fn === "function" 判断,因为期望参数 fn 是函数,如果不是,那就应该抛出异常。
    no1xsyzy
        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();

    })());
    no1xsyzy
        50
    no1xsyzy  
       2020-06-23 14:11:57 +08:00
    @no1xsyzy #49 这个因为 v2 排版会糟糕…… 只有空格问题,用 Fixed code 过一遍即可。
    IGJacklove
        51
    IGJacklove  
       2020-06-23 14:16:12 +08:00 via Android
    @dremy 也不会把,现在 ts 都有?. 和??各种操作了,要是都 if 判空不得累死你?
    zxcslove
        52
    zxcslove  
       2020-06-23 14:42:25 +08:00
    @ChanKc 抓到根本了
    xcatliu
        53
    xcatliu  
       2020-06-23 14:42:59 +08:00   ❤️ 1
    @dremy 你怕是没读过 React 官方文档吧。React 的标准写法分明是 <div>fn && fn(abc)</div>
    https://reactjs.org/docs/conditional-rendering.html#inline-if-with-logical--operator

    BrettD
        54
    BrettD  
       2020-06-23 14:56:32 +08:00
    @dremy 初学编程的时候不都是要学到这个短路写法吗…这种常规写法怎么在你那里成政治不正确了……
    whileFalse
        55
    whileFalse  
       2020-06-23 15:06:08 +08:00
    @dremy 这种写法出现的时候你大概还不会写程序。
    Sapp
        56
    Sapp  
       2020-06-23 15:06:09 +08:00
    现在用这个:fn?.()
    zhjie
        57
    zhjie  
       2020-06-23 15:07:21 +08:00
    对于 js 来说 这么写基本没有心智负担。甚至面试都会提问。
    maichael
        58
    maichael  
       2020-06-23 15:09:20 +08:00
    @ChanKc #33 上 TS 也解决不了这问题,你不能担保调用你这个函数的人也用的 TS,而且也存在 fn 可以为空的情况。
    goodboy95
        59
    goodboy95  
       2020-06-23 15:12:34 +08:00
    @ChanKc js 里面记住非 true 的情况感觉是基本吧,而且这个明显就是只为了回避 null 和 undefined. 这都有心智负担的话,我只能怀疑拿到代码的人以前根本就没碰过 js,临时被拉去维护 js 项目。只要是写 js 吃饭的,这种代码应该都是瞄一眼就过去的事情。
    Jirajine
        60
    Jirajine  
       2020-06-23 15:13:13 +08:00 via Android
    这个就是 js 逻辑运算符的魔法:
    当多个 &&串联时,执行到第一个 truthy 的表达式;
    当多个||串联时,执行到第一个 false-thy 的表达式;
    但我比较赞同王垠博客上的观点:短路机制是给程序优化执行效率的,不是给程序员拿来炫技的。
    ChanKc
        61
    ChanKc  
       2020-06-23 15:14:16 +08:00 via Android
    @maichael 如果是完全内部使用的函数,ts 可以解决问题。我刚刚在 playground 上试了一下,指定 fn 为 Function 类型,如果 fn 是空就会编译错误。如果是对外的函数,这个判断也需要假设用户传入的要么是 falsy 的值要么是函数。那么为什么不干脆假设用户传入的就是个函数?
    maichael
        62
    maichael  
       2020-06-23 15:18:25 +08:00
    @ChanKc #57 因为你没法这么假设,需求完全可能是 fn 的类型是 Function | undefined,这是需求层面决定的,传了我就执行,不传我就不执行,这是很正常的需求。
    ChanKc
        63
    ChanKc  
       2020-06-23 15:18:49 +08:00 via Android
    @goodboy95 Cay S Horstman 就觉得这个不是基本的。Douglas Crockford 也建议“Use booleans in all conditions”
    ChanKc
        64
    ChanKc  
       2020-06-23 15:20:21 +08:00 via Android
    @maichael 如果需求是这样,显式的===undefined 然后让 minifier 去 minify 不好吗
    ChanKc
        65
    ChanKc  
       2020-06-23 15:25:37 +08:00 via Android
    @goodboy95 要达到你这个要求,你就要在招聘的时候让每个应聘者背出 falsy 的值,确保不会有别的团队写 c 的写 java 的调岗到你的团队,然后你才可以放心地使用各种 truthy 和 falsy 的 hack 而保证不出错
    no1xsyzy
        66
    no1xsyzy  
       2020-06-23 15:47:28 +08:00
    @Jirajine #60 说反了吧…… 另外,stackoverflow 上都是喊 falsy 的…… (虽然我第一次是在 codegolf meta 上看到的)(又想起你的黑历史了,不会英文强行秀)
    @ChanKc #42 这其实在 Reddit 和 StackOverflow 上都有过讨论。这个其实是 Shell 带下来的毛病。
    #65 不过,你在招聘时会让每个应聘者背出三位一体甚至九九八十一宫格吗?需要背出字符串对象的全部方法吗?我第一次看到这个表达方式我就大致猜到什么意思,那之前写的甚至是 Pascal 。
    bojackhorseman
        67
    bojackhorseman  
       2020-06-23 15:49:36 +08:00
    这也能吵起来。。。
    ChanKc
        68
    ChanKc  
       2020-06-23 15:55:31 +08:00 via Android
    @no1xsyzy 我当然猜得到,问题根本不在短路,而是在强制类型转换。JS 的强制类型转换规则对别的语言的程序员来说是很奇葩的
    no1xsyzy
        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 是标准形态好多了。
    optional
        70
    optional  
       2020-06-23 16:06:09 +08:00
    @dremy 在 js 的世界里, &&才是政治正确。
    Jirajine
        71
    Jirajine  
       2020-06-23 16:07:58 +08:00 via Android
    @no1xsyzy 没有反,&&遇到 true 就短路所以是执行到第一个 truethy 的表达式后停止,当然这里说执行不准确应该是 evaluate 。
    不是我秀英文,这个词我中文表示出来。而且这俩本来就是词典里没有的生造词,忘了别人怎么写的了我就随手打出来,能表达清意思就够了,论坛回帖又不是写论文,何必咬文嚼字。
    ChanKc
        72
    ChanKc  
       2020-06-23 16:16:15 +08:00 via Android
    @no1xsyzy 是,隐式的自动类型转换,一个笔误
    DOLLOR
        73
    DOLLOR  
       2020-06-23 16:25:58 +08:00   ❤️ 2
    请用最新写法 [fn?.()] ,更简单易读,其他的都别争了,省点口水吧。
    proger
        74
    proger  
       2020-06-23 16:47:05 +08:00
    @DOLLOR 老哥 你的这个写法是什么意思 ,可以举个例子吗?谢谢
    Marstin
        75
    Marstin  
       2020-06-23 16:50:07 +08:00
    @DOLLOR 学到了
    DOLLOR
        76
    DOLLOR  
       2020-06-23 16:51:29 +08:00
    @progerchai

    就是?.操作符,不包括方括号,我把引号打成方括号了。
    可以参见这里:
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
    ke1vin
        77
    ke1vin  
       2020-06-23 17:27:04 +08:00
    不用判断类型?
    ChanKc
        78
    ChanKc  
       2020-06-23 17:53:53 +08:00 via Android
    @DOLLOR 或者 fn ?? fn()
    感谢,又看了眼 spec
    ChanKc
        79
    ChanKc  
       2020-06-23 17:54:39 +08:00 via Android
    @ChanKc 噢我这个是错的
    no1xsyzy
        80
    no1xsyzy  
       2020-06-23 18:07:51 +08:00
    @Jirajine #71 提问:
    1 && 2 && 3 && 4 = ?
    null || undefined || 0 || "" = ?
    && 是遇到 false 短路啊,遇到 true 继续,不然怎么是 if(a){b} 呢
    no1xsyzy
        81
    no1xsyzy  
       2020-06-23 18:08:34 +08:00
    @Jirajine #71 秀英文是上次的事,你想不起来或者不想提就算了。
    iamppz
        82
    iamppz  
       2020-06-23 19:19:57 +08:00 via iPhone
    js 不这么写,ts 会这么写,因为类型检查有编译器处理
    proger
        83
    proger  
       2020-06-23 19:55:19 +08:00
    @DOLLOR 感谢 明白了
    Jirajine
        84
    Jirajine  
       2020-06-23 20:05:13 +08:00
    @no1xsyzy #80 好吧是我弄反了,自己印证了上面的观点:尽量避免这么用。
    回帖搞反顶多被网友批判一番,关键业务逻辑搞反造成重大损失可能就得跑路了。
    ericls
        85
    ericls  
       2020-06-23 20:14:11 +08:00 via iPhone
    @iamppz ts 有 optional chaining.
    auroraccc
        86
    auroraccc  
       2020-06-23 20:28:01 +08:00
    a && a.b && a.b.c && a.b.c()
    a?.b?.c
    cigarzh
        87
    cigarzh  
       2020-06-23 21:48:12 +08:00
    函数式编程基操

    不要用面向对象的思想思考函数式编程的玩意…
    royzxq
        88
    royzxq  
       2020-06-24 00:10:11 +08:00
    偷懒的时候会这么写
    back0893
        89
    back0893  
       2020-06-24 00:15:31 +08:00
    有 fn 就执行
    灭有就不执行
    不是很常规的写法
    iamppz
        90
    iamppz  
       2020-06-24 08:32:35 +08:00
    @ericls 习惯了,React 的条件渲染和 shell 都是这个语法
    fuwu1245
        91
    fuwu1245  
       2020-06-24 10:08:04 +08:00
    如果 fn 不是函数呢?那 fn()不就是个错了么
    donghui1993
        92
    donghui1993  
       2020-07-28 14:00:56 +08:00
    正确写法应该时这个吧:typeof(fn)==='function' && fn(),不过通常约定 fn&&fn() 传递的一定是函数
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5097 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 43ms · UTC 05:45 · PVG 13:45 · LAX 21:45 · JFK 00:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.