JavaScript中的可选链接[重复]

Posted

技术标签:

【中文标题】JavaScript中的可选链接[重复]【英文标题】:Optional Chaining in JavaScript [duplicate] 【发布时间】:2014-11-28 19:22:02 【问题描述】:

我最近使用 Swift 进行了很多编程。今天,当我遇到问题时,我在 JavaScipt 中做了一些工作:

javascript 中有没有类似于可选链的东西?没有任何变量来防止undefined is not an object 的方法?

例子:

function test()
   if(new Date() % 2)
      return value: function()/*code*/;
   
 

test().value();

会失败一半,因为有时test 返回未定义。

我能想到的唯一解决方案是函数:

function oc(object, key)
   if(object)
      return object[key]();
   


oc(test(), 'value');

我希望能够做类似的事情:

test()?.value()

问号后面的部分只有在test返回一个对象时才会执行。

但这不是很优雅。有更好的吗?运算符的神奇组合?

编辑我知道我可以重写test 来返回一些东西。但我想知道是否有类似可选链接的东西。我对上述示例的特定解决方案不感兴趣。如果无法控制返回未定义的函数,我也可以使用。

【问题讨论】:

test() 返回 undefined 时你希望 value() 返回什么? @ZaheerAhmed 错误或未定义。真的没关系。 可以在未定义的情况下包装现有函数返回一个默认值,无需重写。您还可以在调用时使用三元 (x?y:z)() 或默认运算符 (x||y)()。 我在想你可以对每个你想要默认的包装器使用相同的包装器,即使只是一组函数名和一个 map(),但也许我不明白目标.函数在 JS 中很容易出错,所以它不应该采用重复或样板。 RE:编辑,“(x=test()) && x.value()” 比包装器短,或者如果你有时返回一个真值而不是一个对象, (x=test()) && x.value && x.value();但是对函数进行操作的可重用函数会留下更简洁的代码。 是的,我知道。我只是想知道 JavaScript 中是否有类似可选链接的东西,因为 JS 充满了惊喜。 【参考方案1】:

可选链已登陆 JS。我们可以通过?. 运算符在对象属性访问中使用可选链接。它允许我们尝试访问可能不存在的对象的属性(即undefined)而不会引发错误。

这是一个代码示例:

const obj = 
  foo: 
    bar: 1
  
;

// If we try to access property which doesn't exists
// it just returns undefined
console.log(obj.baz);

try 
  // Now we try to access a property of undefined which throws an error
  obj.baz.foz;
 catch (e) 
  console.dir(e.message);


// Now we use the optional chaining operator ?.
// We get undefined instead of an error
console.log(obj.baz?.foz);
            
console.log(obj.foo?.bar);

【讨论】:

【参考方案2】:

目前这是第 4 阶段提案,您可以在此处查看进度:https://github.com/tc39/proposal-optional-chaining

今天就可以使用 babel 插件了:https://www.npmjs.com/package/babel-plugin-transform-optional-chaining

2020 年 1 月 11 日更新: Babel 现在默认支持可选链 https://babeljs.io/blog/2020/01/11/7.8.0

可选链接运算符拼写为?.。它可能出现在三个位置:

obj?.prop       // optional static property access
obj?.[expr]     // optional dynamic property access
func?.(...args) // optional function or method call

注意事项:

为了让foo?.3:0被解析为foo ? .3 : 0(向后兼容的需要),在词法语法级别添加了一个简单的lookahead,这样?.的字符序列就不会被解释在这种情况下作为单个标记(?. 标记不能紧跟十进制数字)。

也值得一试:

https://github.com/tc39/proposal-nullish-coalescing

https://github.com/babel/babel/tree/master/packages/babel-plugin-proposal-nullish-coalescing-operator

【讨论】:

这应该是 2020 年的首选答案。【参考方案3】:

var Obj = Prop: name: 'peter'

console.log(Obj.Prop.name) console.log(Obj?.Prop?.name)

在第一句话中,您只是在访问对象属性。问题在于,如果您发现 Prop 不是对象,它将引发异常。这就是optional chainig operator 的原因。

假设你尝试做Obj.Prop2.name。 你会得到Uncaught TypeError: Cannot read property 'name' of undefined 如果相反,您执行了Obj.Prop2?.name,您只会收到undefined 作为值,而不是异常。

这在访问深度嵌套的属性时特别有用。

警告:这是一个相对较新的 JS 功能,尚未在所有浏览器中实现,因此在将其用于生产应用程序时要小心。

【讨论】:

【参考方案4】:

可选链终于在 JavaScript 标准中了!

这里有几个例子:

// properties
foo?.bar
foo?.bar()
foo?.bar.baz()
foo?.bar?.baz()

// indexing
foo?.[0]
foo?.['bar']

// check if a function is defined before invoking
foo?.()
foo.bar?.()
foo?.bar?.()

这比大多数人用来手动检查空值的方法要好得多

而不是评估

foo?.bar

对于这个小代码sn-p我们都习惯写

foo ? foo.bar : null

它实际上计算为

foo == null ? undefined : foo.bar

适用于所有虚假值,如空字符串、0 或 false。


与问题无关,但您可能也对?? 运算符感兴趣。

它的用途与|| 相似,只是它只检查 null 或 undefined。

例如:

foo ?? bar

将等同于:

foo != null ? foo : bar

这是一项非常新的功能,因此即使很多用户已经使用支持此功能的浏览器,您仍然希望使用工具将其转换为旧版本的 javascript。

【讨论】:

【参考方案5】:

你可以使用

test() && test().value();

var testResult = test();
testResult && testResult.value();

如果你问我,这与 Swift 的可选链最相似。

【讨论】:

test() && test().value() 是不合适的,如果test 有副作用或者如果test 返回除nullundefined 以外的虚假值,当然如果test() 仍然失败没有value 属性,或者它的value 属性不是函数。【参考方案6】:

在纯 JavaScript 中,您必须进行类型检查或构建代码,以便您知道对象将存在。

CoffeeScript 是一种编译为 JavaScript 的语言,如果您愿意考虑使用预处理语言,它提供了一个存在运算符 ?. 用于安全链接。

还有另一个讨论 here 关于为什么你不能在 JS 中重现这种行为。

还有一个讨论 on the ESDiscuss forums 关于在 JavaScript 的未来版本中添加存在运算符。不过,它似乎并没有走得太远,当然离实际使用还很遥远。在这一点上更多的想法。

【讨论】:

我接受了你的回答,因为它确实回答了我的问题,不像下面的其他答案,因为它提供了一些有趣的信息。【参考方案7】:

如果 test 是一个对象方法,你总是可以return this;

但是为什么要通过创建模拟函数来防止此类错误呢?

【讨论】:

OP 提出了一个关于安全链接的一般性问题,而不是如何构建特定功能以确保安全。【参考方案8】:

如果条件不满足,返回一个什么都不做的 noop 函数呢?

function test()
   if(new Date() % 2)
      return value: function()/*code*/;
   
   return value: function() /* just return a type consistent with the function above */ 
 

【讨论】:

这只是一个例子。我说的是我无法控制的功能。 明白了。对不起。您需要像 Groovy 中的 ?. 运算符。 JS中没有这样的东西。 @sebnukem - 现在有针对该运营商的建议 - 请参阅我的回答

以上是关于JavaScript中的可选链接[重复]的主要内容,如果未能解决你的问题,请参考以下文章

javascript中的可选参数[重复]

Javascript:函数中的可选参数[重复]

Python中的类/函数中的可选参数[重复]

proto 3 中的可选(重复)字段

AngularJS 表单。 JSON中的可选属性[重复]

烧瓶 add_url_rule 中的可选参数 [重复]