Недавно наткнулся на статью про
очередной фреймворк JS по названием Imba. Сначала приводится примеры кода на JS, а затем то же самое на этом очередном фреймворке:
Ниже показана простая JS-функция, которая возвращает наибольшее из двух переданных ей чисел, или, если эти числа равны, значение false.
function findGreatest(num1, num2) {
if (num1 > num2) {
return num1
} else if (num2 > num1){
return num2
} else {
return false
}
}
Теперь напишем то же самое на Imba.
def findGreatest num1, num2
if num1 > num2
num1
elif num2 > num1
num2
else
false
Затем, соответственно, автор указывает на преимущества Imba перед чистым JS:
- длинное слово "function",
- куча скобок,
- частое употребление return
То ли автор знает только основы синтаксиса JS, причем устаревшие, и не знает как переписать функцию с учетом его требований. То ли пытается ввести людей заблуждение (хотя делать это на хабре довольно глупо).
Чтобы подобных заблуждений о длине кода JS не было, давайте немного потренируемся в том, как сделать функцию проще, понятнее и читабельней
Сокращение кода
1. if...else
Давайте и начнем с вышеупомянутой функции и попробуем ее сократить:
function findGreatest(a, b) {
if (a > b) {
return a
} else if (b > a){
return b
} else {
return false
}
}
1) Выражение в скобках состоят из одной строки, а потому мы их можем убрать:
function findGreatest(a, b) {
if (a > b) return a
else if (b > a) return b
else return false
}
2) Избавляемся от "else". Зачем они здесь, если return и так не дает пройти дальше?
function findGreatest(a, b) {
if (a > b) return a
if (b > a) return b
return false
}
3) Используем сокращенную запись конструкции if...else, тем самым оставив один return
function findGreatest(a, b) {
return (a > b) ? a
: (b > a) ? b
: false
}
4) Знак ">" выше по приоритету, чем "?", а потому мы можем опустить скобки
function findGreatest(a, b) {
return a > b ? a
: b > a ? b
: false
}
5) Перепишем ее как анонимную функцию, т.е. записав в переменную
const findGreatest = function(a, b) {
return a > b ? a
: b > a ? b
: false
}
6) Это позволит следующим шагом записать ее как стрелочную функцию, т.е. избавившись от длинного ненавидимого некоторыми программистами слова "function"
const findGreatest = (a, b) => {
return a > b ? a
: b > a ? b
: false
}
7) Еще одно преимущество стрелочной функции - возможность убрать return совсем, для чего мы должны написать функцию в круглых скобках
const findGreatest = (a, b) => (a > b ? a : a < b ? b : false)
8) Чисто для справки - в круглых скобках мы можем писать не только одну строку. В ней мы можем написать и несколько строк, отделяя их запятыми, например можем добавить строчку "a = a/b".
const findGreatest = (a, b) => (a = a/b, a > b ? a : a < b ? b : false)
9) Читаемость конечно упадет, но для пары строк несильно. Если строк больше, можем перенести на несколько строк, как обычную функцию
const findGreatest = (a, b) => (
a = a/b,
a > b ? a : a < b ? b : false
)
Таким образом первоначальную функцию мы сократили до одной строки. Удобно ли для него это или нет - выбор автора, а выбора, как видим, немало. Лично мне нравится 2 вариант как самый читаемый и 7 - как самый короткий.
2. Switch
Одна из самых непривычных конструкций js. Многими считается устаревшей, кажется чужеродной, а постоянные вставки "break" бесят чуть ли не всех. Тем не менее в том же мейкере он часто используется для считывания направления персонажа. К примеру
в этом посте используется подобная функция:
const move = function (direction) {
let code;
switch(direction) {
case 2:
code = 'Game_Character.ROUTE_MOVE_DOWN';
break;
case 4:
code = 'Game_Character.ROUTE_MOVE_LEFT';
break;
case 6:
code = 'Game_Character.ROUTE_MOVE_RIGHT';
break;
case 8:
code = 'Game_Character.ROUTE_MOVE_UP';
break;
}
return code
}
1) Мы конечно можем записать брейки в одну строчку, при этом читаемость упадет не сильно
const move = function (direction) {
let code;
switch(direction) {
case 2: code = 'Game_Character.ROUTE_MOVE_DOWN'; break;
case 4: code = 'Game_Character.ROUTE_MOVE_LEFT'; break;
case 6: code = 'Game_Character.ROUTE_MOVE_RIGHT'; break;
case 8: code = 'Game_Character.ROUTE_MOVE_UP'; break;
}
return code
}
2) Но можно вообще отказаться от свитча и использовать объект
const move = function (direction) {
let code = {
'2': 'Game_Character.ROUTE_MOVE_DOWN',
'4': 'Game_Character.ROUTE_MOVE_LEFT',
'6': 'Game_Character.ROUTE_MOVE_RIGHT',
'4': 'Game_Character.ROUTE_MOVE_UP'
}
return code[direction];
}
3) А уже этот объект можем сразу возвращать
const move = function (direction) {
return {
'2': 'Game_Character.ROUTE_MOVE_DOWN',
'4': 'Game_Character.ROUTE_MOVE_LEFT',
'6': 'Game_Character.ROUTE_MOVE_RIGHT',
'8': 'Game_Character.ROUTE_MOVE_UP'
}[direction];
}
Для кого-то это может показаться непривычным, но по мне так подобный вариант не менее чужероден, чем switch
3. if ... else с объектами
В мейкере у игрока и событий похожие методы, а потому часто можно встретить подобную конструкцию
function setParam (params, player) {
if (player) {
...;
}
else {
...;
}
return;
}
Давайте сократим подобную запись взяв как пример подобие функции из
этого поста
function setParam (params, value, player) {
if (player) {
player[params] = value;
}
else {
$gamePlayer[params] = value;
}
return;
}
которую мы вызываем, указывая третий параметр, если мы хотим изменить свойство у события
setParam('_opacity', 0.5, $gameMap.event(1))
и не указываем, если хотим вызвать изменение свойств у героя
setParam('_opacity', 0.5)
1) Перепишем функцию в краткую запись
function setParam (params, value, player) {
(player) ? player[params] = value : $gamePlayer[params] = value;
}
2) Мы можем переписать выражение
(player) ? player[params] = value
как
а значит подобным образом можем переписать и всю функцию:
function setParam (params, value, player) {
(player || $gamePlayer)[params] = value;
}
Итог:
Чем хорошо JS? Тем, что синтаксис дает выбор писать так, как нравится. Можно писать в одну строчку, а можно топорно но читаемо. Можно через стандартные старые конструкции, а можно через функции. Это я еще не говорил о
"new Function", о котором можно почитать самостоятельно