V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
devwolf
V2EX  ›  Node.js

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

  •  1
     
  •   devwolf · 2020-04-16 14:29:18 +08:00 · 15664 次点击
    这是一个创建于 1714 天前的主题,其中的信息可能已经有所发展或是发生改变。
    举例
    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  
    Flourite
        1
    Flourite  
       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  
       2020-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
    刚开始看到时,我也是很震惊的。
    但是实话实说,这个语法的确很实用,不对吗?
    littleylv
        13
    littleylv  
       2020-04-16 14:40:51 +08:00
    写 swift 的时候经常这么写。现在的语言很多都开始互通有无了,都会相互借鉴对方的一些东西
    oneisall8955
        14
    oneisall8955  
       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,比不了后端可以自己决定版本
    xianxiaobo
        25
    xianxiaobo  
       2020-04-16 15:26:15 +08:00
    有意思,学到了
    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:00
    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#首创的吧?
    luzemin
        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' 的写法,不是很简洁。
    chouchoui
        68
    chouchoui  
       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,看别人的库经常这种语法
    overflow99
        72
    overflow99  
       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   ·   实用小工具   ·   4775 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 05:37 · PVG 13:37 · LAX 21:37 · JFK 00:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.