Знаете ли вы, что существует четыре способа написания переключателя в JavaScript? Знаете ли вы это или нет, я не знаю.
Насколько мне известно, существует только один способ написания оператора переключения JavaScript. Но когда дело доходит до обработки ветвей, существует множество способов их написания. Метод записи ветки if можно считать одним, метод записи ветки переключения можно считать вторым, а третий — использовать режим стратегии. Если также включены условные операторы, то их ровно четыре.
но главный герой этой статьи — Switch. Всем известно, что переключатель обычно записывается как переменная переключателя или выражение и константа регистра. Ну, например, для оценки в сто баллов 90 и выше считается отличным, 80 и выше и ниже 90 считаются хорошими, 60 и выше и ниже 80 считаются квалифицированными, а ниже 60 считаются неквалифицированными. Используя переключатель, это. вероятно, будет написано так:
functioncalcGrade(score) { константная линия = оценка/10 0; переключатель (линия) { случай 10: случай 9: вернуть «Отлично»; случай 8: вернуть «хорошо»; случай 7: случай 6: вернуть «квалифицированный»; по умолчанию: вернуть «неквалифицированный»; } }
В коде score / 10 | 0
имеет тот же эффект, что и Math.floor(score / 10)
, который заключается в делении на 10 для получения целой части частного.
Этот переключатель используется довольно хорошо, и метод округления, позволяющий избежать использования длинного списка ветвей if...else, также является хитрым трюком.
Но сейчас правила изменились и разделительный балл между квалифицированным и хорошим снижен с 80 до 75 баллов. Что нам делать?
Вышеописанный метод округления по-прежнему возможен, но на этот раз делитель уже не 10, а 5. Соответственно, падежей гораздо больше:
Лучше использовать 9 падежей. если... еще.
Это? На самом деле есть более простой способ записи с использованием переключателя:
functioncalcGrade(score) { переключатель (истина) { оценка случая >= 90: вернуть «Отлично»; оценка случая >= 75: вернуть «хорошо»; оценка случая >= 60: вернуть «квалифицированный»; по умолчанию: вернуть «неквалифицированный»; } }
Это немного странно? Это вовсе не обычная регистр-константа выражения переключения, а полная противоположность, регистр-выражение константы переключения! Если вы возьмете эту программу и запустите ее, вы обнаружите, что проблем вообще нет. Поскольку - переключатель и регистр сопоставляются в соответствии с ===
, не имеет значения, является ли это выражением или константой, или, другими словами, за переключателем и регистром может следовать выражение!
Да, выражение!
Таким образом, в приведенном выше примере изменение switch(true)
switch( 2 > 1)
имеет тот же эффект.
Хорошо, мой разум открыт. Неважно, сколькими способами вы можете написать переключатель. Следующее, на что стоит обратить внимание, это вариант переключателя.
: я увидел, что в C# есть выражение переключателя, и завидую. Можно ли его реализовать?
Не волнуйтесь, все в JavaScript может быть выражением... Если нет, просто используйте IIFE для инкапсуляции одной
функцииcalcGrade(score) { возврат (значение => { переключатель (истина) { значение регистра >= 90: вернуть «Отлично»; значение регистра >= 75: вернуть «хорошо»; значение регистра >= 60: вернуть «квалифицированный»; по умолчанию: вернуть «неквалифицированный»; } })(счет); }
Обратите внимание, что здесь в качестве параметра IIFE используется score
, поскольку при фактическом использовании может потребоваться передать выражение. В этом случае его следует оценить заранее и только один раз (во избежание побочных эффектов замещения).
Однако такая инкапсуляция, очевидно, бессмысленна. Если вы действительно хотите инкапсулировать ее таким образом, лучше инкапсулировать ее как стратегию:
functioncalcGrade(score) {. return ((value, Rules) => Rules.find(({ t }) => t(value)).v)( счет, [ { t: n => n >= 90, v: «Отлично» }, { t: n => n >= 75, v: «Хорошо» }, { t: n => n >= 60, v: «Квалифицированный» }, { t: () => true, v: "неквалифицированный" }, ] ); }
Каждая стратегия представляет собой объект, содержащий тестер ( t
) и значение ( v
). тестер — это функция оценки, которая передает значение, которое необходимо оценить, то есть выражение здесь, в switch (表达式)
, и это выражение также передается в качестве параметра IIFE после предварительной оценки. Процесс применения стратегии прост и груб: нужно найти первую стратегию, отвечающую условиям, и извлечь ее ценность.
Конечно, эта стратегия немного излишняя. Когда вам действительно нужно использовать стратегию, стратегия обычно представляет собой не значение, а поведение, то есть функцию.
Мы знаем, что в операторе переключения каждый вариант находится в одной и той же области видимости, поэтому одну и ту же локальную переменную нельзя объявить в двух операторах случая. Хотя перенос с помощью { }
может решить эти проблемы, код выглядит не очень хорошо, особенно будьте осторожны и не забудьте break
. Если вы используете стратегию, она может выглядеть приятной для глаз, и вам не придется беспокоиться о проблеме прорыва:
здесь, в демонстрационных целях, в поведении стратегии сначала будут выведены результаты, а затем уровень вернулся.
функция CalcGrade (оценка) { return ((значение, правила) => Rules.find(({ t }) => t(значение)).fn(значение))( счет, [ { т: n => n >= 90, фн: счет => { const оценка = «Отлично»; console.log(оценка, оценка); возвратный балл; } }, { т: n => n >= 75, фн: счет => { константная оценка = «хорошо»; console.log(оценка, оценка); возвратный балл; } }, { т: n => n >= 60, фн: счет => { константная оценка = «пройдено»; console.log(оценка, оценка); возвратный балл; } }, { т: () => правда, фн: счет => { константная оценка = «неквалифицированный»; console.log(оценка, оценка); возвратный балл; } }, ] ); }
Код действительно немного длинный, поскольку в нем есть стратегическая логика поведения. Если его действительно собираются использовать в качестве выражения переключения, часть стратегии должна быть выражением, не слишком длинным. В приведенном выше коде поведение стратегии аналогично и может быть инкапсулировано в функцию, чтобы ее можно было записать в виде выражения:
functioncalcGrade(score) { const printGrade = (оценка, балл) => { console.log(оценка, оценка); возвратный балл; }; return ((значение, правила) => Rules.find(({ t }) => t(значение)).fn(значение))( счет, [ { t: n => n >= 90, fn: Оценка => printGrade("Отлично", оценка) }, { t: n => n >= 75, fn: Оценка => printGrade("Хорошо", оценка) }, { t: n => n >= 60, fn: Оценка => printGrade("квалифицированный", оценка) }, { t: () => true, fn: Оценка => printGrade("неквалифицированный", оценка) }, ] ); }
Теперь он выглядит презентабельно?
Вышеупомянутые коды имеют разные формы и выполняют схожие действия, и нет смысла сравнивать, какой из них лучше. Что бы вам ни нравилось, вы элегантны; что бы вам не нравилось, вас не жалуют. В разных ситуациях просто выбирайте подходящий подход. Приведенный выше код использует find()
для поиска стратегии. Если вместо этого используется filter()
, это будет другая история.