在 js 中为什么如下方式会找不到值? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
qq309187341
V2EX    Javascript

在 js 中为什么如下方式会找不到值?

  •  
  •   qq309187341 2023-01-04 10:38:41 +08:00 4362 次点击
    这是一个创建于 1043 天前的主题,其中的信息可能已经有所发展或是发生改变。
    let a = {
    b: {
    c: {
    d: 1
    }
    }
    }

    let z = 'c.d'
    console.log(a.b[z]) // undefined
    为什么?
    如何才能正常找到
    35 条回复    2023-01-04 20:52:44 +08:00
    DingJZ
        1
    DingJZ  
       2023-01-04 10:40:59 +08:00
    js 本来就不支持这种玩法,可以用第三方的库,lodash 之类的
    qq309187341
        2
    qq309187341  
    OP
       2023-01-04 10:42:51 +08:00
    @DingJZ 不借用第三方,有什么别的写法,如果 z 只有一层 z='c'这样是能找到 c 的,但是再加一层就找不到了
    GressJoe
        3
    GressJoe  
       2023-01-04 10:43:20 +08:00
    eval ,不过容易 boom
    vagary
        4
    vagary  
       2023-01-04 10:46:24 +08:00   2
    哈哈哈哈哈
    a={b:{'c.d':1}}; z='c.d'; console.log(a.b[z])能找到
    AV1
        5
    AV1  
       2023-01-04 10:47:21 +08:00
    要么直接用 lodash ,要么自己参考 lodash 的源码自己实现一个 get 方法。
    我倒是好奇有什么编程语言能这样来的?
        6
    thinkershare  
       2023-01-04 10:48:19 +08:00
    因为 c.d 是一个合法的属性,JS 的对象本质是个 string|symbol-> any 的字典映射。
    chenmobuys
        7
    chenmobuys  
       2023-01-04 10:49:41 +08:00
    啥语言能这样写,这估计是第三方库的处理吧
    wangtian2020
        8
    wangtian2020  
       2023-01-04 10:53:34 +08:00   1
    let a = {
    b: {
    c: {
    d: 1,
    },
    },
    }

    let z = 'c.d'
    console.log(eval(`a.b.${z}`)) // 1
    rongchuan
        9
    rongchuan  
       2023-01-04 10:53:51 +08:00   5
    @qq309187341
    你声明的'c.d'是一个 string 。a.b[z]是从 a 的 b 属性这个对象上,去找 key 值是 z 的 value ,也就是找 key 值是'c.d'的 value 。显然没有这个 value
    这跟第三方库没关系,你没有理解 key 的概念,.不是随便就能.的
    lower
        10
    lower  
       2023-01-04 10:54:56 +08:00
    a.b['c']['d'] 能找着
    qq309187341
        11
    qq309187341  
    OP
       2023-01-04 10:55:36 +08:00
    @rongchuan 哦。我明白了,c.d 是一个整体,而不是 c 下的 d 。所以合在一起就成了 a.b.'c.d'是这样对吧。哈哈哈哈
    qq309187341
        12
    qq309187341  
    OP
       2023-01-04 10:56:42 +08:00
    @lower 哈哈哈,你这个也行。我理解错了。确实要用你这样的写法才可以
    heishu
        13
    heishu  
       2023-01-04 11:31:27 +08:00
    #8 和 #10 是两种可行的方法,一个是处理字符串,一个是对象依次找值
    pendulum
        14
    pendulum  
       2023-01-04 11:34:18 +08:00
    有点想当然了,JS 根本没有这种特性
    hervey0424
        15
    hervey0424  
       2023-01-04 11:38:37 +08:00
    let a = { 'b.c': 123, b: { c: 456 } };
    console.log(a.b.c); // 456
    console.log(a['b.c']); //123
    KMpAn8Obw1QhPoEP
        16
    KMpAn8Obw1QhPoEP  
       2023-01-04 11:41:19 +08:00 via Android
    我居然看了好久才明白你的代码意图是什么。。。。所以反过来我想问的是 哪个语言能支持你这样的写法取值?
    mynameislihua
        17
    mynameislihua  
       2023-01-04 11:44:09 +08:00
    lodash get
    webcape233
        18
    webcape233  
       2023-01-04 11:49:37 +08:00 via iPhone
    什么样的需求这是...
    zhouyg
        19
    zhouyg  
       2023-01-04 11:55:56 +08:00
    根本原因 js 不知道你传入的 c.d 是一个整体的字符串 key 还是可以分割的访问 key ,这里是有歧义的。支持这个特性也很简单,那就是在语言层面新增一个语法来消除这个歧义
    1t1y1ILnW0x5nt47
        20
    1t1y1ILnW0x5nt47  
       2023-01-04 11:57:02 +08:00
    可以用 Object.defineProperty 劫持它的 key,然后把 c.d 转化一下
    caocong
        21
    caocong  
       2023-01-04 12:06:32 +08:00   2
    z.split('.').reduce((res, val)=>res[val],a.b)
    venfiw
        22
    venfiw  
       2023-01-04 12:52:02 +08:00
    let a = {
    b: {
    c: { d: 1}
    }
    }

    let z = 'c.d';
    console.log(a.b[z]) // undefined
    console.log(Object.keys(a.b))

    你可以通过这个可以看到 a.b 里只有一个键值:'c' 并没有'c.d'
    如果你把 c 改为‘c.d' 那么 a.b[z]就可以正常输出
    777777
        23
    777777  
       2023-01-04 14:32:53 +08:00
    写 go 的,看见这种语法直接震惊
    aust
        24
    aust  
       2023-01-04 14:43:14 +08:00
    这种写法你要打印的写法等同于
    {
    "c.d": 1
    } 而不是 {
    c: {
    d: 1
    }
    }
    Arthit
        25
    Arthit  
       2023-01-04 16:12:20 +08:00
    console.log(a.b["c"]["d"]);
    libook
        26
    libook  
       2023-01-04 16:18:47 +08:00   1
    题主提供了一个典型的 bug 案例。因为实际工程上,更多的情况是我们会预期给 z 传入单个字段名,但意外传入路径就 bug 了。所以通常这样用需要小心,如果 z 是用户输入的要做好校验。
    weixiangzhe
        27
    weixiangzhe  
       2023-01-04 16:54:12 +08:00
    那就是手写个 get
    ```js
    function get(obj, path, def) {
    var fullPath = path
    .replace(/\[/g, '.')
    .replace(/]/g, '')
    .split('.')
    .filter(Boolean);

    return fullPath.every((step)=>{
    return !(step && (obj = obj[step]) === undefined);
    }) ? obj : def;
    }

    let a = {
    b: {
    c: {
    d: 1
    }
    }
    }

    let z = 'c.d'
    // console.log(a.b[z]) // undefined


    console.log(get(a,'b.c.d'))

    br />```
    horseInBlack
        28
    horseInBlack  
       2023-01-04 17:06:32 +08:00
    const {
    b: {
    c: { d: z },
    },
    } = a;

    console.log(z);

    连续解构赋值
    https://developer.mozilla.org/zh-CN/docs/Web/Javascript/Reference/Operators/Destructuring_assignment
    chenyu0532
        29
    chenyu0532  
       2023-01-04 18:07:58 +08:00
    连续解构赋值吧。
    你们玩的是真 high ,学习归学习,工作里我可不敢这么用,怕同事打我
    z782297190
        30
    z782297190  
       2023-01-04 18:19:48 +08:00
    字符串 . 和 属性访问器 . 是不同的,js 引擎不认字符串 .
    KMpAn8Obw1QhPoEP
        31
    KMpAn8Obw1QhPoEP  
       2023-01-04 18:29:18 +08:00 via Android
    @777777 小场面 莫慌莫慌 写 JS 的震惊。。
    mwjz
        32
    mwjz  
       2023-01-04 18:38:39 +08:00
    let a = {
    b: {
    c: {
    d: 1
    }
    }
    }

    let z = 'c.d'

    const c = z.split('.').reduce((pre, curr) => pre[curr], a.b);
    imingyu
        33
    imingyu  
       2023-01-04 18:42:57 +08:00
    为什么?
    因为你语法写错了!
    为什么语法是 a.b.c.d 而不是 a.b['c.d']?
    因为规定!
    lynan
        34
    lynan  
       2023-01-04 20:51:57 +08:00
    https://imgur.com/EHwVAgx.png
    这样写才可以取到值,因为在[]里是 key 名
    lynan
        35
    lynan  
       2023-01-04 20:52:44 +08:00
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1298 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 17:19 PVG 01:19 LAX 09:19 JFK 12:19
    Do have faith in what you're doing.
    ubao msn 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