20

我最近用 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以返回一些东西。但我想知道是否有类似可选链接的东西。我对上述示例的特定解决方案不感兴趣。如果无法控制返回未定义的函数,我也可以使用它。

4

8 回答 8

20

这是目前的第 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(根据向后兼容的要求),在词法语法级别添加了一个简单的前瞻,以便?.在这种情况下字符序列不会被解释为单个标记(?.标记不能后面紧跟一个十进制数字)。

也值得一试:

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

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

于 2018-03-12T19:12:54.307 回答
7

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

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

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

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

于 2014-10-03T17:44:09.023 回答
4

您可以使用

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

或者

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

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

于 2014-10-04T05:22:07.103 回答
4

可选链已经登陆 JS。?.我们可以通过对象属性访问中的运算符使用可选链接。它允许我们尝试访问可能不存在(即 are 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);

于 2020-07-14T07:49:48.147 回答
1

var Obj = {Prop: {name: 'peter'}}

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

在第一句话中,您只是在访问对象属性。这样做的问题是,如果您发现Prop不是对象,它将引发异常。这就是可选 chainig 运算符的原因。

可以说你尝试做Obj.Prop2.nameUncaught TypeError: Cannot read property 'name' of undefined 如果相反,你会得到Obj.Prop2?.name,你只会收到undefined一个值,而不是异常。

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

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

于 2020-04-16T12:44:01.807 回答
0

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

function test(){
   if(new Date() % 2){
      return {value: function(){/*code*/}};
   }
   return {value: function(){ /* just return a type consistent with the function above */ }
} 
于 2014-10-03T17:45:02.727 回答
0

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

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

于 2014-10-03T17:46:57.230 回答
0

可选链终于在 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

对于这个我们都习惯写的小代码片段

foo ? foo.bar : null

它实际上评估为

foo == null ? undefined : foo.bar

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


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

它具有类似的目的,||只是它只检查 null 或 undefined。

例如:

foo ?? bar

将与以下内容相同:

foo != null ? foo : bar

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

于 2020-03-25T09:26:12.280 回答