V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
black11black
V2EX  ›  问与答

JavaScript 有没有办法当查询某对象不存在某属性时返回一个默认值?

  •  
  •   black11black · 2020-11-13 07:54:32 +08:00 · 1702 次点击
    这是一个创建于 1477 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,需要实现的功能是我有某对象 A,程序中调用 A 时会不可预期地访问其属性,而这个属性他不一定有。可否实现当访问 A 没有的属性时,调用某个函数,给他生成一个动态的返回值。

    就是类似像 java 的 @value 和 python 的魔术方法那样的功能,js 有办法实现吗,寻一 js 大佬,谢谢。

    第 1 条附言  ·  2020-11-13 08:46:41 +08:00
    贴个条,大概看了一眼大家回复看来是没有原生方法,只能说这语言还是做得太轻量了啊。

    之前为什么没自己写因为如果有办法不需要修改已有代码那么大部分时候应该这么做,尤其是在复杂系统中。如果原生不支持再考虑自己造的问题。
    20 条回复    2020-11-13 18:35:14 +08:00
    Cbdy
        1
    Cbdy  
       2020-11-13 08:02:24 +08:00 via Android
    Proxy
    Mutoo
        2
    Mutoo  
       2020-11-13 08:03:18 +08:00
    使用代理对象,可以拦截 get 方法,加入你需要的逻辑。

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
    jingcoco
        3
    jingcoco  
       2020-11-13 08:07:12 +08:00 via iPhone
    麻烦的一点的是:自己写个方法不就行了。
    代码好看一点的话,可以查查 js 的 get set,封装一下
    其他的估计得用到 babel
    murmur
        4
    murmur  
       2020-11-13 08:18:20 +08:00
    这就是被语法糖限制了思路,你直接写一个 getSomeValue 方法不就完了,取属性都调用这个,想怎么改怎么改
    rodrick
        5
    rodrick  
       2020-11-13 08:31:43 +08:00   ❤️ 1
    xiangyuecn
        6
    xiangyuecn  
       2020-11-13 08:41:28 +08:00
    js 目测是最简单,代码最简洁,因为取值可以写的太随意了😂

    大部分情况下,可这样写( json 中 null 、0 、"" 为逻辑上的无效值):
    var obj={};

    bb=(((obj.aa||{}).cc||[])[123]||{}).zzzzzzzzz||"默认值"

    就问还有那种语言可以这样任性😂
    mcfog
        7
    mcfog  
       2020-11-13 08:46:55 +08:00 via Android
    @xiangyuecn 任意非静态强类型语言(也就是布尔以外的值能用来做逻辑运算)、 逻辑运算是短路求值的(几乎所有) 都可以实现一样的事情,没有例外。

    真想吹甜度好歹拿 optional chaining 来聊
    free9fw
        8
    free9fw  
       2020-11-13 08:49:11 +08:00   ❤️ 1
    obj?.xxx ?? 'default value'
    xiangyuecn
        9
    xiangyuecn  
       2020-11-13 09:04:55 +08:00
    @mcfog #7 那么,请直接说出哪种语言😂 似乎没有比 js 甜的了吧,不管是 android 还是 ios 原生未封装的代码都得写到脑瘫😂

    我 6 楼的那坨 json ( null 、0 、"" 为逻辑上的无效值),取 zzzzzzzzz:

    {"aa":{"cc":[{"zzzzzzzzz":"值"}]}}
    {"aa":{"cc":[{}]}}
    {"aa":{"cc":null}}
    {"aa":{}}
    taro0822
        10
    taro0822  
       2020-11-13 09:06:49 +08:00
    proxy +1
    wenzichel
        11
    wenzichel  
       2020-11-13 09:28:01 +08:00
    @free9fw #8 正解
    tyx1703
        12
    tyx1703  
       2020-11-13 09:29:50 +08:00
    yaphets666
        13
    yaphets666  
       2020-11-13 09:32:20 +08:00
    es2020 为了解决这个问题 提出了楼上的这种语法
    现在一般程序中是这样写 if(a.b&&a.b.c&&a.b.c.d) {....}
    SmallTeddy
        14
    SmallTeddy  
       2020-11-13 09:48:13 +08:00
    这里回复一下 proxy 是 es6 新增的原生 可以设置拦截器 设置在 prototype 上 详情可以参考阮一峰写的 es6——https://es6.ruanyifeng.com/#docs/proxy
    DOLLOR
        15
    DOLLOR  
       2020-11-13 09:49:35 +08:00
    不知道你对“原生方法”定义是啥,但 JS 已经有这种语法了:
    aa?.bb?.cc?dd ?? defaultValue

    当然你可以用 lodash:
    _.get(aa, 'bb.cc.dd', defaultValue)

    方法已经告诉你了,“调用某个函数,给他生成一个动态的返回值”这种需求就不用我教了吧。
    mcfog
        16
    mcfog  
       2020-11-13 12:11:28 +08:00
    @xiangyuecn 所以我说了静态强类型不行,然后你搬出静态强类型的 java 说不行,确实不行啊

    那么我满足你的希望随便说几个吧

    写 python 的同学,至少我在填遗留老坑的时候 xx or None 基本写到吐的,(xx or {'foo': None})['foo'] 也能用
    写 php 的,在老一点的时代,defined('XX') or die 也是写到吐的, $datasource->getSomeArray() || []也是基本操作

    再梳理一下,你说的特性其实只依赖于“布尔以外的类型可以直接参与逻辑运算,并有合理的 falsy 定义” 以及 “上述逻辑运算结果为真时返回原始输入值而不是 true”,这两件事情几乎任何弱类型语言或者是会做动态推断的强类型语言都是满足的,我刚才在路上把后面那个特性说成短路求值了是不准确的,短路求值涉及到类似用法中有副作用的用法,换成你喜欢的 js 的话大概就是

    (await request('has_auth')) || alert(‘没有权限!’)

    这个样子
    Sunyanzi
        17
    Sunyanzi  
       2020-11-13 13:05:43 +08:00
    @mcfog 既然看到了我问一句题外和楼主问题无关的 ... 关于 #16 的那个 php 的例子 ...

    defined( 'XX' ) or die; 不是常规操作吗 ... 空取常量最低也是个 warning ... php8 里升到了 fatal ...

    也就是在我的认知里 ... 这种写法并不是「在老一点的时代」才用 ... 相反在未来肯定会越用越多 ...

    我想了半天 ... 怎么都觉得这不是操作符能够压得住的事情 ...

    所以我想问 ... 是不是说有什么我不知道的方式可以简化这种写法 ..?
    mcfog
        18
    mcfog  
       2020-11-13 14:03:49 +08:00
    @Sunyanzi

    ?额我说“写到吐”就是指这种写法基本操作,不是说有什么更好的,不如说就是因为一个奇怪的语法糖却没啥更好的替代品所以才看到烦……
    还是我没理解对你的疑问?

    关于时代新老的问题,主要是慢慢单入口框架或者不把无关文件放在 public 的做法更常见了,所以就不需要这句话了,composer psr 的话就更不用了,psr 规定了声明类的文件不能有副作用

    我说的是这个用法是特指什么 IN_DISCUZ 之类的,用一个常量存在性确保文件不被 webserver 错误地执行的用法,否则不会 or die 的吧,还是你说的以后用的更多是$x = defined('XX') or 'default value'; 这种? 这种的话确实随着严重级别上调,用的更多说得通……虽然我是 NOTICE 当 bug 修的选手
    across
        19
    across  
       2020-11-13 14:08:39 +08:00
    js 这种连续问号倒是简洁的,不过问号太多了,总觉得是在嘲讽( dota 后遗症)
    Sunyanzi
        20
    Sunyanzi  
       2020-11-13 18:35:14 +08:00
    @mcfog 没有没有 ... 应该是我理解的问题 ...

    我的侧重点在那句「在老一点的时代」 ... 也不知道怎么就以为是说新的时代就有更方便的写法了 ...

    原来是说新的时代里这种写法不那么常见了 ... 那确实没毛病 ...

    另 ... Notice 当 bug 修是没错的 ... error_reporting( E_ALL ); 是自信心和技术力的表现 ...
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1000 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 22:49 · PVG 06:49 · LAX 14:49 · JFK 17:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.