Що таке JavaScript-умова без роботи?


121

Що таке JavaScript-умова без роботи? Як passкоманда Python .

  • Один варіант - це просто порожня функція: function() {}
  • jQuery пропонує $.noop()просто виклик порожньої функції вгорі.
  • Чи прийнятно просто вводити значення falseабо 0?

У контексті ... все це працює без помилки в Chrome:

var a = 2;
(a === 1) ? alert(1) : function() {};
(a === 1) ? alert(1) : $.noop();
(a === 1) ? alert(1) : false;
(a === 1) ? alert(1) : 0;

EDIT: Багато людей відповіли: "Не робіть цього! Змініть структуру коду!" Це нагадує мені публікацію, де хтось запитав, як нюхати браузер. Він отримав безліч дописів із повідомленням: "НЕ РОБИТИ! Це зло!", Але ніхто не сказав йому, як нюхати браузер . Це не огляд коду. Уявіть, що ви маєте справу зі застарілим кодом, який неможливо змінити, і без передачі якоїсь функції він призведе до помилки. Або, просто, так хоче клієнт, і вони мені платять . Тож, з повагою, будь ласка, дайте відповідь на питання : Який найкращий спосіб вказати функцію "без операції" в JavaScript?

EDIT2: Як щодо одного з них?

true;
false;
0;
1;
null;

7
Чому б не просте, якщо твердження?
epascarello

11
Жодна з цих альтернатив 0фактично не є кращою (або гіршою). Я б сказав, що правильно робити - це if (a === 1) doSomething();не використовувати, ? :коли це не має сенсу.
Pointy

6
Ви зловживаєте потрійним оператором з побічним ефектом. Якщо потрібно, зробітьif (statement) action; else ;
mplungjan

Так falseчи 0буде працювати; nullце приємний спосіб висловити не-оп.
Метт

3
Я сподіваюся, що у потрійника є якась необхідність, яку ми не можемо побачити з якоїсь причини ... Дуже схоже, що ти ускладнюєш свій код, щоб почувати себе круто (ми це все зробили!)
Stachu

Відповіді:


95

Щоб відповісти на початкове запитання, найелегантніша та акуратніша реалізація функції noop у чистому Javascript (про що також тут йде мова ) - Function.prototype . Це відбувається тому:

  1. Function.prototype - це функція:

typeof Function.prototype === "function" // returns true

  1. Його можна викликати як функцію і по суті нічого не робить, як показано тут:
setTimeout(function() {
      console.log('Start: ', Date.now());
      Function.prototype();
      console.log('End  : ', Date.now());
    }, 1000);

Хоча це "справжній нооп", оскільки більшість браузерів, схоже, нічого не роблять, щоб виконати нооп, визначений таким чином (і, отже, зберегти цикли процесора), можуть бути деякі проблеми з ефективністю, пов'язані з цим (як це також згадують інші в коментарях або в інші відповіді).

Однак, якщо говорити, ви можете легко визначити власну функцію noop, і, фактично, багато бібліотек і фреймворків також надають функції noop. Нижче наведено кілька прикладів:

var noop = function () {};           // Define your own noop in ES3 or ES5
const noop = () => {};               // Define in ES6 as Lambda (arrow function)
setTimeout(noop, 10000);             // Using the predefined noop

setTimeout(function () {} , 10000);  // Using directly in ES3 or ES5
setTimeout(() => {} , 10000);        // Using directly in ES6 as Lambda (arrow function)

setTimeout(angular.noop, 10000);     // Using with AngularJS 1.x
setTimeout(jQuery.noop, 10000);      // Using with jQuery

Ось алфавітний перелік різних реалізацій функцій noop (або пов'язані з ними дискусії чи пошук Google):

AngularJS 1.x , Angular 2+ ( Мабуть ,не існує вбудованої реалізації - використовуйте власну, як показано вище), Ember , jQuery , Lodash , NodeJS , Ramda , React ( Схоже , це не реальна реалізація - використовуйте власну як показано вище), RxJS , Підкреслення

BOTTOM LINE : Хоча Function.prototype є елегантним способом вираження noop у Javascript, однак, можуть виникнути деякі проблеми, пов’язані з його використанням. Отже, ви можете визначити та використовувати свій власний (як показано вище) або використовувати той, який визначений бібліотекою / рамкою, яку ви могли використовувати у своєму коді.


5
Це має бути відповіддю. Можна навіть скористатися, Function.prototype()якщо вам не потрібен тайм-аут, і ви хочете, щоб він виконувався відразу.
навесні завантажено

1
setTimeout(Function(), 10000);
ієгік

@iegik: +1. Так, ви праві. Усі наступні еквівалентні: setTimeout (функція () {}, 10000); АБО setTimeout (нова функція (), 10000); або setTimeout (функція (), 10000); АБО setTimeout (функція, 10000); оскільки граматика Javascript та реалізація конструктора функцій дозволяють ці конструкції.
Алан CS

5
У ES6 або з використанням вавилону чи іншого транспілера (( )=>{};)технічно Pure JS і набагато коротший, function () {}але точно еквівалентний.
Рей Фосс

2
Мені було цікаво знайти непридатну конструкцію для ефективного відключення коду налагодження у моїй програмі. У C / C ++ я б використовував макроси. Я перевіряв, присвоюючи свій fn Function.prototype і приурочував його, порівнюючи результати, просто маючи оператор if у функції, щоб повернутися негайно. Я також порівняв їх з результатами простого видалення функції з циклу. На жаль, Function.prototype взагалі не спрацював. виклик порожньої функції був значно кращим за продуктивністю, навіть швидше, ніж виклик функції за допомогою простого тесту "якщо" всередині, щоб повернутися.
ведмедик

72

Найбільш коротка і продуктивний Noop є порожній функцією стрілка : ()=>{}.

Функції стрілок працюють у всіх браузерах, окрім IE ( якщо потрібно, перетворення бабеля ): MDN


()=>{} vs. Function.Prototype

  • ()=>{}на 87% швидше, ніж Function.prototypeу Chrome 67.
  • ()=>{}на 25% швидше, ніж Function.prototypeу Firefox 60.
  • ()=>{}на 85% швидше, ніж Function.prototypeу Edge (15.06.2018) .
  • ()=>{}на 65% менше коду, ніж Function.prototype.

Тест нижче нагрівається за допомогою функції стрілки, щоб надати зміщення Function.prototype, але функція стрілки є явним переможцем:

const noop = ()=>{};
const noopProto = Function.prototype;

function test (_noop, iterations) {
    const before = performance.now();
    for(let i = 0; i < iterations; i++) _noop();
    const after = performance.now();
    const elapsed = after - before;
    console.info(`${elapsed.toFixed(4)}MS\t${_noop.toString().replace('\n', '')}\tISNOOP? ${_noop() === undefined}`);
    return elapsed;
}

const iterations = 10000000
console.info(`noop time for ${iterations.toLocaleString()} iterations`)
const timings = {
    noop: test(noop, iterations),
    noopProto: test(noopProto, iterations)
}

const percentFaster = ((timings.noopProto - timings.noop)/timings.noopProto).toLocaleString("en-us", { style: "percent" });
console.info(`()=>{} is ${percentFaster} faster than Function.prototype in the current browser!`)


1
Я створив тест jsPerf для порівняння деяких варіантів: noop-function . Схоже, що у Firefox 54 всі альтернативи здаються приблизно рівнозначними; у Chromium 58 Function.prototypeрізко повільніше, але жоден з інших варіантів не має певної переваги.
Лукас Веркмайстер

_=>{}на один символ менше і робить те ж саме.
Ross Attrill

@RossAttrill * подібне - _=>{}має єдиний параметр. Якщо хтось використовує TypeScript з досить суворим конфігурацією, це не компілюється. Якщо ви його зателефонуєте, ваш IDE, ймовірно, скаже вам, що він приймає єдиний параметр, який може бути будь-якого типу (як JavaScript, так і особливо TypeScript у vscode).
Чемберлен

15

все, що ви прагнете досягти тут, неправильно. Потрійні вирази не повинні використовуватися як повноцінне висловлювання, лише у виразі, тому відповідь на ваше запитання:

жодна з ваших пропозицій, замість цього виконайте:

var a = 2;
if (a === 1)
    alert(1)
// else do nothing!

тоді код легко зрозумілий, читабельний і настільки ж ефективний, наскільки він може отримати.

Чому це ускладнює, коли це може бути простим?

редагувати:

Тож, чи в основному команда "не працює" вказує на нижчу структуру коду?

Ви пропускаєте мою думку. Все вищесказане стосується потрійного виразу x ? y : z.

Але команда без операцій не має сенсу для мов вищого рівня, таких як Javascript.

Зазвичай він використовується на мовах нижчого рівня, таких як збірка або С, як спосіб змусити процесор нічого не робити за одну інструкцію для цілей часу.

В JS, чи робите ви 0;, null;, function () {};або пусте вираз, є великі шанси , що він буде ігноруватися інтерпретатором , коли він читає, але перш , ніж вона буде інтерпретуватися, так що врешті-решт, ви просто зробити вашу програма буде завантажується повільніше за дійсно мінімальну кількість часу. Нота Бене : Я припускаю, що я не причетна до жодного широко використовуваного перекладача JS, і є певний шанс, що кожен перекладач має свою стратегію.

Якщо ви використовуєте щось трохи складніше, наприклад, $.noop()або var foo = function () {}; foo(), тоді інтерпретатор може здійснити невикористаний виклик функції, який в кінцевому підсумку зіпсує кілька байтів стека вашої функції та кілька циклів.

Єдиною причиною, коли я бачу функцію, таку як $.noop()існувала, було б можливість надавати функцію зворотного виклику якійсь функції подій, яка б викинула виняток, якщо вона не може викликати цей зворотний виклик. Але тоді це обов'язково функція, яку вам потрібно надати, і давати їй noopім'я - це гарна ідея, тому ви говорите своїм читачам (і це ви можете через 6 місяців), що ви навмисно надаєте порожню функцію.

Зрештою, немає такого поняття, як "неповноцінна" чи "вища" структура коду. Ви правильно чи неправильно в тому, як використовуєте свої інструменти. Використовувати потрійник для свого прикладу - це як використовувати молоток, коли ви хочете накрутити. Це спрацює, але ви не впевнені, що можете щось повісити на цей гвинт.

Що можна вважати «неповноцінним» або «вищим» - це алгоритм та ідеї, які ви вводите у свій код. Але це інша річ.


1
Тож, чи в основному команда "не працює" вказує на нижчу структуру коду?
kmiklas

3
@kmiklas: Я не можу сказати, що я ніколи не знаходив законної потреби в NOOP, поза межами асемблера.
Метт Берланд

@zmo: я розумію вашу думку щодо того, як ваші коментарі стосуються потрійного виразу; всі, здається, пропустили мою думку, що це був лише показовий приклад заклику до функції "Без операції".
kmiklas

1
Звичайно, є причини, які хочуть / потребують функції без відключення. Не робіть широких узагальнень, спираючись на 12 секунд глибокої думки про щось. JavaScript - це мова, яка робить функції повністю керованими як змінні. Припустимо, у вас є потреба відключити функцію без явного тесту? Це було б ідеально для цього. Якщо у вас є функція, яка з’являється часто, наприклад, виправлення помилки, було б непогано мати можливість вимкнути її, переназначивши функцію на неоперативний, а не додавати додатковий код для тестування певної змінної кожного разу, коли функція з'являлася .
ведмедик

2
@bearvarine дякую за високу думку, яку ви маєте про мене :-D. Ви абсолютно праві в своєму коментарі, але це не зовсім для дизайну коду, а просто макет дизайну за допомогою хак. Те, що ви описуєте, також називається виправленням мавп, і в цьому є причина ;-)
змо

7

Я думаю, що jQuery noop()здебільшого призначений для запобігання збою коду шляхом надання функції за замовчуванням, коли запитуваний недоступний. Наприклад, враховуючи наступний зразок коду, $.noopвибирається, якщо fakeFunctionвін не визначений, що запобігає fnкраху наступного виклику :

var fn = fakeFunction || $.noop;
fn() // no crash

Потім, noop()дозволяє зберегти пам'ять, уникаючи записувати одну і ту ж порожню функцію кілька разів скрізь у своєму коді. До речі, $.noopце трохи коротше, ніж function(){}(6 байт збережено за маркер). Отже, між вашим кодом та порожнім шаблоном функцій немає зв’язку. Використовуйтеnull , falseабо , 0якщо хочете, в вашому випадку не буде ніяких побічних ефектів. Крім того, варто зазначити, що цей код ...

true/false ? alert('boo') : function(){};

... абсолютно марно, оскільки ви ніколи не будете називати цю функцію, і ця ...

true/false ? alert('boo') : $.noop();

... ще більше марно, оскільки ви викликаєте порожню функцію, яка точно така ж, як ...

true/false ? alert('boo') : undefined;

Замінимо потрійний вираз на an if вислів, щоб побачити, наскільки він марний:

if (true/false) {
    alert('boo');
} else {
    $.noop(); // returns undefined which goes nowhere
}

Ви можете просто написати:

if (true/false) alert('boo');

Або навіть коротше:

true/false && alert('boo');

Зрештою, щоб відповісти на ваше запитання, я думаю, що "звичайна операція без використання" - це та, яка ніколи не пишеться.


1
Однак іноді доводиться надавати функцію. Наприклад, з обіцянками тоді (fn, fn) іноді ви хочете надати другу функцію, але не першу. тому вам потрібно щось для власника місця ...mypromise.then($.noop, myErrorhandler);
Джон Генкель

3

Я використовую:

 (0); // nop

Щоб перевірити час виконання цього запуску:

console.time("mark");
(0); // nop
console.timeEnd("mark");

результат: оцінка: 0,000мс

Використання Boolean( 10 > 9)може бути зведене до просто того, ( 10 > 9)що повертає true. Придумавши ідею використовувати єдиний операнд, я повністю очікував, (0);що повернеться false, але він просто поверне аргумент назад, як це можна переглянути, виконавши цей тест на консолі.

> var a = (0);
< undefined
> a
< 0

1
багато хто спробує це отриматиargument 0 is not a function
Шепіт коду

4
Ви просто призначите 0. IMO noopмає бути функцією, яка оцінює undefinedрезультат.
Чемберлен

1
Як це твердження (0); присвоєння 0 ?, де знак var та рівності? Немає імені функції перед (0), тому я не бачу, як це може бути аргументом? якщо спробувати typeof ((0)), він повертається як число. Коли я відповідав на запитання, я надавав твердження, яке використовую для імітації НОП, але я готовий змінити свою відповідь на просто використання; представляти порожню заяву
Яйця

1
Я думаю (0); є прийнятним рішенням питання ОП. Я думаю, що люди плутаються через те, що вони знайшли цю сторінку, шукаючи функцію, яка нічого не робить, а не заяву, яка нічого не робить. ОП не допомагає, спочатку пропонуючиfunction(){} як рішення. Виклик (0)()спричинитьTypeError: 0 is not a function
Бенджамін

Я мав на увазі var a = (0); . Оператор не повинен змінювати пам’ять, і ваш приклад призначення призначений саме для цього. Сам (0)по собі може вважатися марним беззастережним (у JavaScript існує нескінченна кількість таких, тому нічого, що робить ваш приклад тут особливим).
cchamberlain

2

Не існує абсолютно жодних проблем або штрафних санкцій за використання Function.prototypeнад () => {}.

Основна перевага Function.prototype- це функція сингтона, а не повторне визначення нової анонімної функції кожного разу. Особливо важливо використовувати такий режим, як Function.prototypeпри визначенні значень за замовчуванням та запам'ятовуванні, оскільки він дає вам послідовний вказівник об'єкта, який ніколи не змінюється.

Причина, яку я рекомендую, Function.prototypeа не Functionчерез те, що вони не однакові:

Function() === Function()
// false

Function.prototype() === Function.prototype()
// true

Крім того, орієнтири інших відповідей вводять в оману . Насправді Function.prototypeефективність працює швидше, ніж () => {}залежно від того, як ви пишете та запускаєте тест:

Ви не можете довіряти еталонам JS << Спеціально вимагаючи орієнтирів у цьому питанні.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.