rtivital
2/12/2016 - 6:27 PM

Разбор решения к заданию №2 "Начинаем программировать"

Разбор решения к заданию №2 "Начинаем программировать"

// Тесты для проверки функции getMessage
var test = function(expected, actually) {
  var tested = 'Тест <b style="color:' + (expected === actually ? 'green">пройден' : 'red">провален') + '</b>.';
  var result = '<b>Ожидалось:</b> ' + expected + ' | <b>Результат:</b> ' + actually + ' | ' + tested;
  console.log(result);
  return result;
};

var results = [];
var testsList = document.getElementById('tests');
var fragment = document.createDocumentFragment();

results.push(test('Я попал в Россию', getMessage(true, 'Россию')));
results.push(test('Я попал в Нарнию', getMessage(true, 'Нарнию')));
results.push(test('Я никуда не попал', getMessage(false, 'Россию')));
results.push(test('Я никуда не попал', getMessage(false, 'Нарнию')));
results.push(test('Я прыгнул на 300 сантиметров', getMessage(3)));
results.push(test('Я прыгнул на 4500 сантиметров', getMessage(45)));
results.push(test('Я прошёл 6 шагов', getMessage([1, 2, 3], {})));
results.push(test('Я прошёл 71 шагов', getMessage([14, 21, 36], '')));
results.push(test('Я прошёл 37 метров', getMessage([1, 2, 3], [4, 6, 7])));

results.forEach(function(item) {
  var li = document.createElement('li');
  li.innerHTML = item;
  fragment.appendChild(li);
});

testsList.appendChild(fragment);
'use strict';

function getMessage(a, b) {
  var sum = function(x, y) {
    return x + y;
  };

  var multiply = function(current, index) {
    return current * b[index];
  };

  if (typeof a === 'boolean') {
    return a ? 'Я попал в ' + b : 'Я никуда не попал';
  }

  if (typeof a === 'number') {
    return 'Я прыгнул на ' + (a * 100) + ' сантиметров';
  }
  // Более короткий вариант с тернарным оператором
  // Код становится менее читабельным
  // Лучше использовать более длинный вариант
  if (Array.isArray(a)) {
    return Array.isArray(b)
      ? 'Я прошёл ' + a.map(multiply).reduce(sum) + ' метров'
      : 'Я прошёл ' + a.reduce(sum) + ' шагов';
  }
}
'use strict';

function getMessage(a, b) {
  var message;
  // Оператор typeof не обзательно обворачивать скобками
  // typeof a === 'boolean' будет работать также хорошо

  // Всегда (за очень редким исключением) следует использовать
  // оператор строгого сравнения ===, а не ==
  // Иногда это может привести к ошибкам
  // http://learn.javascript.ru/comparison#сравнение-разных-типов
  if ( (typeof a) == 'boolean' ) {
    // При использовании тернарного оператора не обязательно заключать условие в скобки
    // a ? (message = 'Я попал в ' + b) : (message = 'Я никуда не попал');
    // Также следует избегать выполнения выражений с тернарным оператором
    // Лучше записать вот так
    // message = a ? 'Я попал в ' + b : 'Я никуда не попал';
    // Полученное выражение можно сразу же вернуть, минуя запись в переменную
    // return a ? 'Я попал в ' + b : 'Я никуда не попал';
    (a) ? (message = 'Я попал в ' + b) : (message = 'Я никуда не попал');
    return message;
  }

  if ( (typeof a) == 'number' ) {
    message = 'Я прыгнул на ' + (a * 100) + ' сантиметров';
    return message;
  }

  if ( Array.isArray(a) && !Array.isArray(b) ) {
    // Функция function(x, y) { return x + y; } используется дважды
    // Поэтому её лучше записать в переменную и не дублировать код
    // var sum = function(x, y) { return x + y; };
    // А потом использовать с методом reduce
    // var sumArray = a.reduce(sum);
    var sumArray = a.reduce(function(x, y) {
      return x + y;
    });

    message = 'Я прошёл ' + sumArray + ' шагов';
    return message;
  }

  // Две проверки массивов можно объеденить в одну конструкцию if
  // if (Array.isArray(a)) {
  //   if (!Array.isArray(b)) { ... return 'Я прошёл ' + sumArray + ' шагов'; }
  //   return 'Я прошёл ' + length + ' метров';
  // }
  if ( Array.isArray(a) && Array.isArray(b) ) {
    // Функцию можно объявить заранее, чтобы воспользоваться более
    // коротким способом без промежуточных переменных
    // var multiply = function(current, index) { return current * b[index]; };
    // Вместе с написанной ранее функцией sum можно записать следующим образом
    // var length = a.map(multiply).reduce(sum);
    var multiply = a.map( function(currentValue, index) {
      return currentValue * b[index];
    });

    var length = multiply.reduce(function(x, y) {
      return x + y;
    });

    // Или можно сразу вернуть результат
    // return 'Я прошёл ' + a.map(sum).reduce(multiply) + ' метров';
    message = 'Я прошёл ' + length + ' метров';
    return message;
  }
  // Подробный разбор перебирающих методов массивов можно посмотреть здесь
  // http://jsraccoon.ru/fn-array-methods
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    body { font-family: sans-serif; margin: 0; padding: 0; }
    .tests-container { max-width: 80%; background-color: #f7f7f7; padding: 2rem; margin: 0 auto; }
    code {font-family: 'Consolas', monospace; background-color: #f0f0f0; padding: .2rem .5rem; border: 1px solid #ccc; border-radius: .2rem; }
  </style>
</head>
<body>

  <div class="tests-container">
    <h3>Тестирование функции <code>getMessage</code></h3>
    <ul id="tests"></ul>
  </div>

  <!-- Варианты для тестирования  -->
  <!-- 1. Исходный -->
  <!-- <script src="initial.js"></script> -->

  <!-- 2. Улучшенный -->
  <!-- <script src="better.js"></script> -->

  <!-- 3. Укороченный -->
  <script src="better.js"></script>

  <!-- Подключение тестов -->
  <script src="tests.js"></script>
</body>
</html>
'use strict';

function getMessage(a, b) {
  var sum = function(x, y) {
    return x + y;
  };

  var multiply = function(current, index) {
    return current * b[index];
  };

  if (typeof a === 'boolean') {
    return a ? 'Я попал в ' + b : 'Я никуда не попал';
  }

  if (typeof a === 'number') {
    return 'Я прыгнул на ' + (a * 100) + ' сантиметров';
  }

  if (Array.isArray(a)) {
    if (!Array.isArray(b)) {
      return 'Я прошёл ' + a.reduce(sum) + ' шагов';
    }
    return 'Я прошёл ' + a.map(multiply).reduce(sum) + ' метров';
  }
}