JavaScript中的可选链接

时间:2014-10-03 17:39:39

标签: javascript

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

在JavaScript中是否有类似于可选链接的内容?一种在没有任何变量的情况下阻止undefined is not an object的方法吗?

示例:

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

test().value();

将失败一半的时间,因为有时test返回undefined。

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

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

oc(test(), 'value');

我希望能够做到这样的事情:

test()?.value()

问号后面的部分仅在test返回对象时执行。

但这不是很重要。还有更好的东西吗?运营商的神奇组合?

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

8 个答案:

答案 0 :(得分:6)

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

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

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

还有一个关于在未来版本的JavaScript中添加存在运算符的讨论on the ESDiscuss forums。虽然它似乎并不遥远,但实际上并没有接近实际用途。此时更多的想法。

答案 1 :(得分:5)

这是目前的第1阶段提案,您可以在此查看其进度:

您今天可以使用babel插件:

https://www.npmjs.com/package/babel-plugin-transform-optional-chaining

可选链接操作符拼写?..它可能出现在三个位置:

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-optional-chaining

另外值得一试:

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

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

答案 2 :(得分:4)

您可以使用

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

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

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

答案 3 :(得分: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);

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

如果test是对象方法,您可以始终return this;

但是你为什么要通过创建模拟函数来防止这样的错误呢?

答案 6 :(得分: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

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


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

它的用途与||类似,除了它只检查null或未定义。

例如:

foo ?? bar

将与以下相同:

foo != null ? foo : bar

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

答案 7 :(得分:0)

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功能,尚未在所有浏览器中实现,因此在将其用于生产应用程序时要小心。