在ES6 / Typescript中将_(下划线)变量与箭头函数一起使用


119

我在一个Angular示例中遇到了这个构造,我想知道为什么选择它:

_ => console.log('Not using any parameters');

我知道变量_表示不在乎/不使用,但是由于它是唯一的变量,因此没有任何理由更喜欢使用_:

() => console.log('Not using any parameters');

当然,键入的字符数不能少于一个。在我看来()语法更好地传达了意图,并且还更加具体地说明了类型,因为否则我认为第一个示例应该看起来像这样:

(_: any) => console.log('Not using any parameters');

万一重要,这是使用它的上下文:

submit(query: string): void {
    this.router.navigate(['search'], { queryParams: { query: query } })
      .then(_ => this.search());
}


1
您如何担心从未使用过的参数的类型或类型特异性?

3
我是一名C ++开发人员,所以我想我总是担心类型特异性:-)。
2016年

6
就个人而言,_ =>模式减少了方括号的数量,使其更易于阅读:doStuff()。then(()=> action())vs doStuff()。then(_ => action())。
Damien Golding

Answers:


93

之所以可以使用此样式(可能是在此处使用该样式)的原因_是比短一个字符()

可选括号与可选大括号属于同一样式问题。这在很大程度上取决于品味和代码风格,但是由于一致性,在这里倾向于冗长。

尽管箭头函数允许单个参数不带括号,但它与零,单个解构,单个休止符和多个参数不一致:

let zeroParamFn = () => { ... };
let oneParamFn = param1 => { ... };
let oneParamDestructuredArrFn = ([param1]) => { ... };
let oneParamDestructuredObjFn = ({ param1 }) => { ... };
let twoParamsFn = (param1, param2) => { ... };
let restParamsFn = (...params) => { ... };

尽管is declared but never used错误固定在打字稿2.0为下划线的参数,_也可以触发unused variable/parameter从棉绒或IDE警告。这是反对这样做的一个相当大的理由。

_通常可以用于忽略的参数(如已经解释的其他答案)。尽管这可能被接受,但是这种习惯可能会导致与_Underscore / Lodash命名空间发生冲突,并且在存在多个被忽略的参数时也会引起混淆。因此,正确命名带下划线的参数(在TS 2.0中受支持)是有益的,还节省了找出函数签名的时间以及为什么将这些参数标记为忽略的原因(这违背了将_参数作为快捷方式的目的):

let fn = (param1, _unusedParam2, param3) => { ... };

由于上述原因,我个人认为_ => { ... }代码风格是一种不好的语气,应该避免。


1
它短了一个字符,但对于大多数IDE来说,它的按键操作量相同,因为按(通常带有)。我个人更喜欢使用 p参数,我也想知道它是否有任何性能问题
Mojimi,

67

()语法传达的意图更好恕我直言,也是更具体的类型

不完全是。()表示该函数不包含任何参数,不声明任何参数。该函数的.length值为0。

如果使用_,它将明确指出该函数将被传递一个参数,但是您并不在意。该函数的.length值为1,这在某些框架中可能很重要。

因此,从类型的角度来看,这可能是更准确的操作(尤其是当您不使用any而是键入时_: Event)。正如您所说,键入的字符减少了一个字符,在某些键盘上也更容易触及。


6
我的第一个想法是_仅根据约定使其很明显,在尝试理解该函数时无需考虑任何参数。使用()可以使代码变得很明确,无需扫描代码即可使用_(这将违反约定)。但是,您睁开了眼睛,还考虑了记录传递给函数的值的价值,否则该价值并不总是显而易见的。
暂停

我刚刚意识到我的代码中充满了未使用的_s箭头函数变量,我想知道与使用相比,性能是否存在差异()
Mojimi,

24

我猜_ =>只是用完了,() =>因为_在其他语言中很常见,不允许像JS这样只省略参数。

_ 在Go中很流行,它在Dart中也用于表示参数被忽略,可能还有其他我不知道的参数。


4
我认为Python也遵循这一约定。
Jaime RGP

7
的这种用法_大概是从ML和Haskell等功能语言中借来的,在那里早于Python的发明(更不用说Go,Dart或TypeScript)了。
ruakh

1
Ruby也是这样做的(po-ru.com/diary/rubys-magic-underscore)和F#(以及受ML家族影响的其他语言)
Mariusz Pawelski,2016年

Scala喜欢下划线(includehelp.com/scala/use-of-underscore-in-scala.aspx)。在Scala使用带下划线的匿名类型进行处理之后,需要使用哪种语言?
山姆

我猜Scala也从其他语言中获取了它。在70年代,几乎没有编程语言中的任何东西:D大多数情况下,仅仅是将这些内容组合在一起的新方法。
君特Zöchbauer

11

可以区分这两种用法,并且某些框架使用它来表示不同类型的回调。例如,我认为节点表达框架使用它来区分中间件的类型,例如错误处理程序使用三个参数,而路由使用两个参数。

这种区分看起来像下面的示例:

const f1 = () => { } // A function taking no arguments
const f2 = _ => { }  // A function with one argument that doesn't use it

function h(ff) { 
  if (ff.length === 0) {
    console.log("No argument function - calling directly");
    ff();
  } else if (ff.length === 1) {
    console.log("Single argument function - calling with 1");
    ff(1);
  }
}

h(f1);
h(f2);


1
这是基于Bergi的回答,但我认为添加示例比我乐于对其他人的帖子做更多的编辑。
迈克尔·安德森

0

当我写这篇文章时,给我的印象_是创建没有的箭头功能的唯一方法(),这使我相信使用_可能会有一些次要的优点,但是我错了。@Halt在注释中确认它的行为与其他变量相同,这不是特殊的语言构造。


我想在测试自己时再提到我对这些下划线箭头功能所认识的一件事,而我在任何地方都没有提到。可以在函数中使用下划线作为参数,尽管这可能不是预期的用法,因为它应该表示未使用的参数。为了清楚起见,我真的不建议使用这种方式。但了解诸如codegolf之类的问题,编写最短代码的挑战可能很有用(事实证明,不带即可使用任何字符())。我可以想象一些实际的用例,其中的库使用此功能,即使它们不打算使用该功能,也需要使用它。

例:

// simple number doubling function
f = _=> {
    _ = _ * 2;
    return _;
}

console.log(f(2)); // returns 4
console.log(f(10)); // returns 20

已通过Chrome控制台版本76.0.3809.132(官方内部版本)(64位)进行了测试


1
下划线“ _”是合法的变量名称,而不是特殊的语言构造,仅按约定赋予特殊含义。可以使用下划线前缀将关于未使用参数的Linter警告静音。我想_只是说不使用的最短方法。
暂停

@Halt感谢您的澄清,很高兴知道。实际上,()在我发这篇文章之前,我实际上没有意识到没有箭头功能就可以实现箭头功能,我认为_这是唯一的方法,这就是为什么我决定指出这一点。考虑到这一点,事实证明即使是打高尔夫球也没什么特别的,因为您可以使用常规角色。如您所说,最好仅用于遵循约定。
Matsyir
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.