Використання змінної _ (підкреслення) із функціями стрілок у ES6 / Typescript


119

Я натрапив на цю конструкцію на кутовому прикладі і мені цікаво, чому саме це обрано:

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

Я розумію, що змінна _ означає не хвилює / не використовується, але оскільки це єдина змінна, чи є якась причина віддавати перевагу використанню _ over:

() => 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 ++ в галузі торгівлі, тому, мабуть, мене завжди турбує специфіка типу :-).
Зупинка

6
Особисто шаблон _ => зменшує кількість дужок, що полегшує читання: doStuff (). Тоді (() => action ()) vs doStuff (). Тоді (_ => action ()).
Деміен Голдінг

Відповіді:


93

Причина, по якій цей стиль може бути використаний (і, можливо, чому його тут використовували), полягає в тому, що _він на один символ коротший ().

Необов’язкові дужки потрапляють у той же стиль стилю, що і необов’язкові фігурні дужки . Це питання смаку та стилю коду здебільшого, але багатослівність тут надається перевагою через послідовність.

У той час як функції стрілок дозволяють використовувати один параметр без дужок, він не відповідає нулю, одиночному деструктуванню, одинарному покою та декільком параметрам:

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

Хоча is declared but never usedпомилка була виправлена ​​в TypeScript 2.0 для підкреслених параметрів, _також може викликати unused variable/parameterпопередження від лінера або IDE. Це вагомий аргумент проти цього.

_можна умовно використовувати для ігнорованих параметрів (як уже пояснено в іншій відповіді). Хоча це може вважатися прийнятним, ця звичка може призвести до конфлікту з _простором імен Underscore / Lodash, а також виглядає заплутаним, коли є кілька ігнорованих параметрів. З цієї причини вигідно, щоб правильно названі параметри підкреслених (підтримуються в TS 2.0), також економить час на з'ясування підпису функції і чому параметри позначені як ігноровані (це не відповідає призначенню _параметра як ярлику):

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

З причин, перерахованих вище, я б особисто вважав _ => { ... }стиль коду поганим тоном, якого слід уникати.


1
Це один символ коротший, але це однакова кількість натискань клавіш для більшості IDE, оскільки натискання на (звичайно відбувається із символом a ). Я особисто вважаю за краще використовувати pпараметр, мені також цікаво, чи є у нього проблеми з роботою
Моїмі

68

()Синтаксис передає наміри краще IMHO , а також більш типу конкретних

Не зовсім. ()каже, що функція не очікує ніяких аргументів, вона не оголошує жодних параметрів. Функція .lengthдорівнює 0.

Якщо ви користуєтесь _, то прямо вказано, що функції буде передано один аргумент, але вас це не хвилює. Функція .lengthбуде 1, що може мати значення в деяких рамках.

Отже, з точки зору типу, це може бути більш точним, що потрібно зробити (особливо коли ви не вводите його, anyале, скажімо, _: Event). І, як ви вже сказали, набрати на один символ менше, що також простіше дістати на деяких клавіатурах.


6
Перша моя думка полягала в тому, що _ дає зрозуміло лише умовно, що немає аргументів, які слід враховувати, намагаючись зрозуміти функцію. Використання () робить це явним, не потрібно сканувати код для можливого використання _ (що порушило б умову). Але ви відкрили мені очі, щоб також розглянути значення документального підтвердження того, що існує значення, передане функції, яке інакше не завжди буде очевидним.
Зупинка

Я щойно зрозумів, що мій код повний невикористаних _змінних функцій стрілки, мені цікаво, чи є різниця в продуктивності порівняно з використанням()
Моїмі

24

Я здогадуюсь, що _ =>він просто використовується, () =>тому що _є поширеним в інших мовах, де заборонено просто опускати параметри, як у JS.

_ Популярний в Go, і він також використовується в Dart, щоб вказати, що параметр ігнорується, і, ймовірно, інші, про які я не знаю.


4
Python також дотримується цієї конвенції, я думаю.
Хайме РГП

7
Це використання, _ймовірно, запозичене з функціональних мов, таких як ML та Haskell, де воно давно передувало винайдненню Python (не кажучи вже про Go, Dart або TypeScript).
ruakh

1
також Ruby робить це ( po-ru.com/diary/rubys-magic-underscore ) і F # теж (та інші мови, на які впливає сім'я ML)
Маріуш Паульський

Скала любить підкреслення ( includehelp.com/scala/use-of-underscore-in-scala.aspx ). Які ще мови взяли після того, як Скала робить анонімні типи з підкресленням.
Сем

Я б здогадався, Скала також взяв це з якоїсь іншої мови. Навряд чи є щось у мовах програмування, які не існували вже в 70-х роках: D Переважно нові способи комбінування цього матеріалу.
Günter Zöchbauer

11

Можна відрізнити два звичаї, і деякі рамки використовують це для представлення різних типів зворотних викликів. Наприклад, я думаю, що вузли express Framework використовують це для розрізнення типів проміжного програмного забезпечення, наприклад, обробники помилок використовують три аргументи, тоді як маршрутизація використовує два.

Така диференціація може виглядати як приклад нижче:

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
Це ґрунтується на відповіді Берджі, але я думав, що додавання прикладу трохи більше редагування, ніж я радий зробити комусь іншому.
Майкл Андерсон

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
Підкреслення "_" - це юридична назва змінної, а не особлива конструкція мови, яка лише надається особливим значенням за умовами. Попередження лінійки про невикористані параметри можна заглушити за допомогою префікса підкреслення. Я думаю, _ сам по собі - це лише найкоротший спосіб сказати невикористане.
Привал

@Halt Дякую за уточнення, добре знати точно. Я насправді не усвідомлював, що ти можеш виконувати функції стрілок без того, ()як я зробив цю посаду, я вважав, що _це єдиний спосіб, саме тому я вирішив вказати на це. Зважаючи на це, виявляється, нічого особливого використовувати навіть для гольфу, оскільки ви могли просто використовувати звичайного персонажа. Як ви сказали, краще їх просто використовувати для дотримання конвенцій.
Маційір
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.