请教一下一个使我震惊的 js 语法 ?.(没错,看起来很像三目但却不是:而是.) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
devwolf
V2EX    Node.js

请教一下一个使我震惊的 js 语法 ?.(没错,看起来很像三目但却不是:而是.)

  •  1
     
  •   devwolf 2020-04-16 14:29:18 +08:00 16447 次点击
    这是一个创建于 2003 天前的主题,其中的信息可能已经有所发展或是发生改变。
    举例
    let a = {a:"1",b:"2"}
    console.log(a?.a)

    契机:另一个组的同事在一个 angular 项目里发现了这个语法的使用,
    通过关键字查了一下也就这么个 csdn 的结果
    《 angular 中的 ? 和 !》 https://blog.csdn.net/weixin_30908941/article/details/95594290

    里面除了交代?可以判断前面的变量是否为 null 或 undefined 再执行后面,还有个!判断后面键所对应的值是否为 null 或 undefined,不过没有成功在 js 里再现这个!。

    就我个人在网上的搜索结果来看,感觉这个?.的写法比!!还要冷门,用途的效果上个人感觉类似 react 写 jsx 进行页面渲染时的&&或者?:

    当然,我自己的这些肤浅猜测总结也没什么营养,还请各位有了解或者感兴趣的分析一波这个?.吗
    106 条回复    2020-04-17 19:57:29 +08:00
    1  2  
    dV9zZM1wROuBT16X
        1
    dV9zZM1wROuBT16X  
       2020-04-16 14:32:01 +08:00   1
    这语法在其他语言也不是很罕见的,比如 swift
    asAnotherJack
        2
    asAnotherJack  
       2020-04-16 14:33:19 +08:00   1
    kotlin 也有这种语法
    mercury233
        3
    mercury233  
       020-04-16 14:33:51 +08:00
    可空类型,不算冷门
    murmur
        4
    murmur  
       2020-04-16 14:34:14 +08:00   1
    ?。这语法太超前了,虽然各种 objectPath 类组件早就在用,可以一次访问很深层的节点,不用一层层判空
    cmdOptionKana
        5
    cmdOptionKana  
       2020-04-16 14:34:26 +08:00
    现在主流语言是天下语法一大抄,越来越趋同了。
    skies457
        6
    skies457  
       2020-04-16 14:35:11 +08:00   4
    devwolf
        7
    devwolf  
    OP
       2020-04-16 14:35:50 +08:00
    感谢楼上的各位解疑,原来是其他语言已经存在的语法,get 了
    Lin0936
        8
    Lin0936  
       2020-04-16 14:36:43 +08:00
    最近在 kotlin 里写这个都写吐了. 之前 swift 的项目里也用到很多.
    yaphets666
        9
    yaphets666  
       2020-04-16 14:38:13 +08:00
    我写了一年多 js 也 不知道这个...我是不是太菜了
    crs0910
        10
    crs0910  
       2020-04-16 14:38:48 +08:00   1
    你还可以使用 ?? 来代替 ||,避免需要判断值是不是 0 这种情况
    关键词:Nullish Coalescing
    vivipure
        11
    vivipure  
       2020-04-16 14:39:15 +08:00   1
    dart 也有。这是 ES2020 的新语法,挺好用的,不用在写什么 a && a.b 之类的了。
    aaronlam
        12
    aaronlam  
       2020-04-16 14:39:45 +08:00   1
    刚开始看到时,我也是很震惊的。
    但是实话实说,这个语法的确很实用,不对吗?
    U7Q5tLAex2FI0o0g
        13
    U7Q5tLAex2FI0o0g  
       2020-04-16 14:40:51 +08:00
    写 swift 的时候经常这么写。现在的语言很多都开始互通有无了,都会相互借鉴对方的一些东西
    itechify
        14
    itechify  
    PRO
       2020-04-16 14:42:24 +08:00 via Android   1
    kotlin 里面有,thymeleaf 模板写对象判断非空也是用这里的语法
    islxyqwe
        15
    islxyqwe  
       2020-04-16 14:49:02 +08:00
    新版本 ts 提前支持的 Optional Chaining 等 ES2020 的新语法拉
    liuy1994g
        16
    liuy1994g  
       2020-04-16 14:55:16 +08:00 via Android
    es 里还在提案吧
    noobma
        17
    noobma  
       2020-04-16 14:56:09 +08:00
    关注 ts 的话应该不会觉得这个写法冷门
    Justin13
        18
    Justin13  
       2020-04-16 14:59:15 +08:00 via Android
    建议关注 ECMA262 repo
    luob
        19
    luob  
       2020-04-16 15:03:21 +08:00
    写 js 的不都是天天跟着最新语法标准走吗,这种最近大半年都在谈的语法就算没用过,总不至于没听过吧……

    还是说现在前端已经足够成熟,大家都不学新内容了?
    crz
        20
    crz  
       2020-04-16 15:03:21 +08:00
    主要是新,冷门应该不至于,毕竟很实用
    g00001
        21
    g00001  
       2020-04-16 15:05:01 +08:00
    我觉得还是 aardio 中的直接下标更简洁好用,
    if( a[[b]] ){ } 不管 a 是什么都不会抛异常,不是对象返回 null,可以节省好多代码。

    比 swift,kotlin,js 什么的出现早多了,国产小语言也是有亮点的。
    baozijun
        22
    baozijun  
       2020-04-16 15:09:40 +08:00   1
    Safe calls are useful in chains. For example, if Bob, an Employee, may be assigned to a Department (or not), that in turn may have another Employee as a department head, then to obtain the name of Bob's department head (if any), we write the following:

    bob?.department?.head?.name
    Such a chain returns null if any of the properties in it is null.
    sarlanori
        23
    sarlanori  
       2020-04-16 15:15:10 +08:00   1
    C#也有这个语法了
    murmur
        24
    murmur  
       2020-04-16 15:16:53 +08:00
    @luob 浏览器端不敢瞎 babel,比不了后端可以自己决定版本
        25
    xianxiaobo  
       2020-04-16 15:26:15 +08:00
    有意思,学到了
    xianxiaobo
    yhxx
        26
    yhxx  
       2020-04-16 15:28:33 +08:00
    @liuy1994g 已经进 stage4 了
    jadehare
        27
    jadehare  
       2020-04-16 15:31:43 +08:00
    ts 有插件会自动不上。。虽然我自己写还是 if 判断一下
    zmqking
        28
    zmqking  
       2020-04-16 15:35:08 +08:00
    c# 里面也有!
    9ki
        29
    9ki  
       2020-04-16 15:36:57 +08:00
    要多想
    Lax
        30
    Lax  
       2020-04-16 15:37:53 +08:00
    为了减少对父元素的空置判定,尤其是很多个级别。
    a.b.c.d 这种,if(a) { if(a.b) { if(a.b.c) { a.b.c.d }}}},不想一级一级判断的时候就很方便了。
    goodboy95
        31
    goodboy95  
       2020-04-16 15:38:05 +08:00
    握草,刚刚试了一下,除了?.运算符之外,??运算符也被支持了!
    var a = {sa: 3, sb: 4};
    var b = null;
    console.log(a?.sa ?? 5); // 3
    console.log(b?.sa ?? 5); // 5
    yolee
        32
    yolee  
       2020-04-16 15:51:37 +08:00
    c# 也是用这个判断是否为空的
    lower
        33
    lower  
       2020-04-16 15:53:45 +08:00
    语法糖
    Veneris
        34
    Veneris  
       2020-04-16 15:55:28 +08:00
    dart 也有
    no1xsyzy
        35
    no1xsyzy  
       2020-04-16 15:55:38 +08:00
    https://caniuse.com/#feat=mdn-Javascript_operators_optional_chaining
    太超前了,FF 和 CR 各只过了两个版本,过 babel 可行( angular 可以用大概就是 babel 的原因?)
    早前 coffee 就看到了
    lithbitren
        36
    lithbitren  
       2020-04-16 15:55:49 +08:00
    ?? 和 || 有啥区别啊
    liukangxu
        37
    liukangxu  
       2020-04-16 16:02:05 +08:00
    看来 C#还是有人用的。。。
    apeople
        38
    apeople  
       2020-04-16 16:05:42 +08:00
    angular 也只是能在模板中使用吧,要想在 ts 中使用还是得配置 babel 插件。
    DivineRapierH
        39
    DivineRapierH  
       2020-04-16 16:07:40 +08:00 via iPhone   1
    @Lax #30 这种我一直是用 lodash 的 get 一把梭
    Removable
        40
    Removable  
       2020-04-16 16:07:57 +08:0
    C#里我经常这么用,比判断==null 方便多了
    redam
        41
    redam  
       2020-04-16 16:08:00 +08:00
    @luob 啊,老哥一般是在哪里了解这些新内容的?
    devwolf
        42
    devwolf  
    OP
       2020-04-16 16:09:24 +08:00
    @lithbitren
    https://developer.mozilla.org/zh-CN/docs/Web/Javascript/Reference/Operators/Nullish_coalescing_operator
    摘录:
    由于 || 是一个布尔逻辑运算符,左侧的操作数会被强制转换成布尔值用于求值。任何假值( 0, '',NaN,null,undefined )都不会被返回。这导致如果你使用 0,''或 NaN 作为有效值,就会出现不可预料的后果.
    空值合并操作符??可以避免这种陷阱,其只在第一个操作数为 null 或 undefined 时(而不是其它假值)返回第二个操作数。

    感谢#10 提供了拓展和线索
    lithbitren
        43
    lithbitren  
       2020-04-16 16:13:49 +08:00
    @devwolf 蟹蟹,MDN 常看常新啊
    Ritter
        44
    Ritter  
       2020-04-16 16:35:34 +08:00
    666
    gromit1337
        45
    gromit1337  
       2020-04-16 16:37:56 +08:00
    @vivipure #11 对对
    iugo
        46
    iugo  
       2020-04-16 16:44:37 +08:00
    VS Code + TypeScript 会给我强推这种写法.
    iugo
        47
    iugo  
       2020-04-16 16:46:38 +08:00   1
    iugo
        48
    iugo  
       2020-04-16 16:48:23 +08:00
    推一下前两天我们关于 nullish coalescing operator post: https://zsqk.github.io/news/2020-04-08-nullish-coalescing-operator.html
    klgd
        49
    klgd  
       2020-04-16 16:54:40 +08:00
    上次遇见了一次,搜了半天才知道是干什么的
    还有`!!`
    ZZITE
        50
    ZZITE  
       2020-04-16 17:07:47 +08:00
    Optional Chaining
    去年写的 ts 项目就在用了,在 react 项目中很舒服。
    lneoi
        51
    lneoi  
       2020-04-16 17:10:46 +08:00
    这是新语法啦,很实用的
    AlynxZhou
        52
    AlynxZhou  
       2020-04-16 17:11:51 +08:00   1
    看起来楼主没写过 coffeescript 啊,coffeescript 里面有这个问号运算符
    jtwor
        53
    jtwor  
       2020-04-16 17:13:36 +08:00
    c# 空运算
    Rwing
        54
    Rwing  
       2020-04-16 17:14:32 +08:00
    很棒的语法啊,c#首创的吧?
        55
    luzemin  
       2020-04-16 17:20:43 +08:00
    C#的语法糖
    est
        56
    est  
       2020-04-16 17:23:27 +08:00   1
    ruby 里可以直接 inline 外挂一个 exception 更方便。不管是 . 挂了还是别的什么挂了都能正常执行。
    xuchdeid
        57
    xuchdeid  
       2020-04-16 17:28:35 +08:00
    TypeScript 啊 。。。
    IllBeBack
        58
    IllBeBack  
       2020-04-16 17:30:15 +08:00
    相当于 Ruby 的单身狗运算符 a&.a

    ruby-china.org/topics/30415
    ershierdu
        59
    ershierdu  
       2020-04-16 17:42:25 +08:00
    学 swift 的时候感觉这个有点绕,项目做完后不再写 swift 就忘了
    wszgrcy
        60
    wszgrcy  
       2020-04-16 17:55:16 +08:00 via Android
    ts 3.7 的语法吧
    mrleft
        61
    mrleft  
       2020-04-16 18:03:06 +08:00   1
    g00001
        62
    g00001 
       2020-04-16 18:03:18 +08:00
    c# 6.0 ( 2015 年) 才有 Null 条件运算符,应当是比较晚了。

    国产小语言 aardio 在十多年前就有了类似的语法,不仅仅是对象,任何对象都可以 if( a[[b]] ){ } ,真正的有鸭子的声音就可以当鸭子用,说到偷懒这个事,我们还是行的。

    只能 null 对象,还是会有麻烦,如果是其他类型呢,还是要写判断,偷懒还是不够彻底这不行的。
    jin7
        63
    jin7  
       2020-04-16 18:10:10 +08:00
    php 早就有了
    ansenJ
        64
    ansenJ  
       2020-04-16 18:26:25 +08:00
    ES7+后的新语法 我知道有 但是不知道在哪个版本里
    optional
        65
    optional  
       2020-04-16 18:41:46 +08:00 via iPhone
    js 生态就要经常上来看看 tc39,ts 可以经常看看 roadmap
    ccyu220
        66
    ccyu220  
       2020-04-16 18:45:08 +08:00
    除了 ts , 暂时还不敢用。
    g00001
        67
    g00001  
       2020-04-16 18:45:17 +08:00   1
    PHP 就更晚了,PHP 7 才有 $d = $a->$b->$c ?? 'DEFAULT' 的写法,不是很简洁。
    GenericClass
        68
    GenericClass  
       2020-04-16 18:48:04 +08:00 via iPhone
    C#基本操作,ts 也有
    xrr2016
        69
    xrr2016  
       2020-04-16 18:50:37 +08:00
    Dart 里面经常用...还有 ?? 语法
    Chingim
        70
    Chingim  
       2020-04-16 18:53:42 +08:00 via Android
    多关注 tc39
    en20
        71
    en20  
       2020-04-16 19:00:49 +08:00 via iPhone
    最近写 flutter,看别人的库经常这种语法
    y4ZIZrCL74b9MYl6
        72
    y4ZIZrCL74b9MYl6  
       2020-04-16 19:13:54 +08:00
    很有用 学习了
    mingtianjiayou
        73
    mingtianjiayou  
       2020-04-16 19:53:45 +08:00
    新语法哈哈
    nekochyan
        74
    nekochyan  
       2020-04-16 19:59:11 +08:00
    没记错的话是 es7 新语法吧,一般情况下不敢用,怕不支持
    shenyu1996
        75
    shenyu1996  
       2020-04-16 20:11:43 +08:00
    最近新开项目 下意识在使用 ?. ... 这些语法
    说真的 能少掉好多头发 少些好多代码
    xg4
        76
    xg4  
       2020-04-16 20:12:59 +08:00
    @nekochyan 已经纳入标准,可以用 babel 进行兼容处理
    shenyu1996
        77
    shenyu1996  
       2020-04-16 20:15:32 +08:00
    ```
    {
    name: 'aaa',
    ...(true && {age: 10})
    }
    ```

    比如像这种神奇的写法 真的能让自己少掉好几根头发
    Felldeadbird
        78
    Felldeadbird  
       2020-04-16 20:36:29 +08:00
    我印象中 PHP7 也有这种语法。但是我还是喜欢用传统的:?判断为主。 太新的语法我怕其他人调式出错。就蒙蔽了。
    cnit
        79
    cnit  
       2020-04-16 20:53:49 +08:00
    thymeleaf 里面经常会用到
    cbais7890
        80
    cbais7890  
       2020-04-16 20:57:45 +08:00   1
    可选链啊, 如果用过 Swift 肯定会觉得很熟悉
    实际上 a?.b 就等于 a && a.b 的意思, 防止对不存在的变量读取属性而产生异常
    在处理某些前后端交互的不稳定数据时相当舒服
    LukeChien
        81
    LukeChien  
       2020-04-16 20:58:27 +08:00 via Android
    现在很常见了,以前在模板引擎语法里很常见
    yxcoder
        82
    yxcoder  
       2020-04-16 21:06:01 +08:00   1
    因为 js 里面访问 undefined 或者 null 的成员会报错,所以如果调用很深,譬如这种,a.b.c.d.e.f,为了防止报错,要这么写

    a?a.b?a.b.c?a.b.c.d?a.b.c.d.e?a.b.c.d.e.f:null:null:null:null:null

    巨难看
    所以出了个语法糖

    a?.b?.c?.d?.e?.f
    Pursue9
        83
    Pursue9  
       2020-04-16 21:15:24 +08:00
    C# 还有 ?? ??=

    a?.b 等同于 if(a == null) return null
    还有 a??0 等同于 if(a == null) return 0
    a??=0 等同于 if(a == null){ a = 0; return a;}
    SilentDepth
        84
    SilentDepth  
       2020-04-16 21:23:47 +08:00
    @Pursue9 #83 Logical Assignment Operators,ES 这边已经 Stage 3,如无意外明年就纳入规范了
    IGJacklove
        85
    IGJacklove  
       2020-04-16 21:28:25 +08:00 via Android
    还好吧,flutter 早就有这个语法了,kotlin 也有类似的语法,简单来说就是简化判空操作的,js 听说要新加这个语法,当时跑了是还不能用的
    SilentDepth
        86
    SilentDepth  
       2020-04-16 21:29:56 +08:00
    Optional Chaining 不仅有 foo.bar?.qux ,还有 foo.bar?.( ) 呢
    :-)
    LeiNaD
        87
    LeiNaD  
       2020-04-16 21:35:42 +08:00
    可选链
    bilberry
        88
    bilberry  
       2020-04-16 21:42:40 +08:00
    ES2020 里面的
    weyou
        90
    weyou  
       2020-04-16 23:10:49 +08:00 via Android
    Python PEP505,不过这语法确实有点 magic,不符合 Python 的一贯风格,难怪还没被采纳
    somebody
        91
    somebody  
       2020-04-16 23:21:57 +08:00
    很多语言都有,这个叫 Safe navigation operator, Wikipedia 有 18 种语言的例子
    https://en.wikipedia.org/wiki/Safe_navigation_operator
    jinliming2
        92
    jinliming2  
       2020-04-16 23:23:24 +08:00
    @yxcoder 您这个就算没有 ?. 语法,也可以不用 ?: 啊……
    用 ?: 是丑,但是直接
    a && a.b && a.b.c && a.b.c.d && a.b.c.d.e && a.b.c.d.e.f || null
    也稍微好看一些啊……
    (虽然还是 ?. 更香
    HytonightYX
        93
    HytonightYX  
       2020-04-16 23:37:44 +08:00
    我还写过 webpack 的实现,不过只是用了正则替换来判断,不是很完美。
    TC39 有关于可选链的解释。
    hst001
        94
    hst001  
       2020-04-17 00:11:34 +08:00
    很好用的语法糖,各大语言应该引入
    errolli
        95
    errolli  
       2020-04-17 00:12:25 +08:00
    C#里面就有。。。 后来换到用 Java 的公司就没这个待遇了
    FutherAll
        96
    FutherAll  
       2020-04-17 00:18:05 +08:00 via iPhone
    optional 更适合用来解包判空之类的。
    如果用来判断布尔的话是有歧义的,比如:if (a?.b == 0)或者 if(a?.b == false),到底是 a 为空还是 a 不为空 b 为 false 或者 b 为空
    param
        97
    param  
       2020-04-17 00:50:35 +08:00 via Android
    原来 JS 也有了
    Yumwey
        98
    Yumwey  
       2020-04-17 00:51:57 +08:00 via Android
    可选链,香的很。震惊啥 TS 强推
    guolaopi
        99
    guolaopi  
       2020-04-17 09:30:57 +08:00
    我写 C#,这玩意儿都写了好几年了,基本就是日常。。。。。
    学新语言的时候觉得没有 x?.x 还有 x??y 这种写法很别扭。。。。
    ugu
        100
    ugu  
       2020-04-17 10:13:17 +08:00
    angular 里面经常写
    1  2  
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2618 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 15:19 PVG 23:19 LAX 08:19 JFK 11:19
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86