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
返回除null
或undefined
以外的虚假值,当然如果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中的可选链接[重复]的主要内容,如果未能解决你的问题,请参考以下文章