Почему “return” не возвращает значение?

314
07 марта 2017, 16:38
cell(numX, numY) {
  this.cells.map((cell) => {
    if (numX == cell.opts.numX && numY == cell.opts.numY) {
      console.log(cell);
      return cell;
    }
  });
}

Код выше определенно находит необходимый Cell (так как console.log() выводит то, что необходимо). Но вот return это значение не возвращает. Для меня остается непонятным, почему код ниже работает как надо, а этот код работать не хочет. Прошу объяснить.

cell(numX, numY) {
    let xcell;
    this.cells.map((cell) => {
      if (numX == cell.opts.numX && numY == cell.opts.numY) {
        console.log(cell);
        xcell = cell;
        return;
      }
      return;
    });
    return xcell;
  }

Кстати, хотелось бы добавить. Мне необходимо, чтобы, когда нужный элемент найден, он тут же возвращался бы, не заставляя цикл доходить до конца (заведомо известно, что найден может быть только один элемент). Тут дело в том, что поиск будет производится по довольно большому количеству элементов, и лишние проверки тут ни к чему. Поэтому как только элемент найден - нужно его сразу вернуть. А Debug-Console в Chrome показывает мне, что даже после того, как элемент найден и return сработал, цикл продолжает выполняться в поисках других элементов, что в корне неверно, ведь return должен не только вернуть значение, но и прекратить выполнение блока, в котором он находится (насколько мне известно).

Answer 1

Вы используете метод map, который возвращает новый массив, где каждый элемент является результатом вызова функции, которую вы передает в качестве параметра

На простом примере

const nums = [1, 2, 3, 4]
const doubleNums = nums.map( n => n * 2 )
// doubleNums= [2, 4, 6, 8]

Что происходит в этом коде: мы передаем map функцию n => n * 2, это значит, что мы пройдет по нашему массиву циклом, умножим каждый элемент массива на 2 и из результатов создадим новый массив, который будет записан в переменную doubleNums

Поэтому ваш код работает не так как вы ожидаете, он не вернет вам нужную ячейку, а просто вызовет функцию для каждого элемента вашего массива.

cell(numX, numY) {
  this.cells.map((cell) => {
    if (numX == cell.opts.numX && numY == cell.opts.numY) {
      console.log(cell);
      return cell;
    }
  });
}

В вашем случае лучше использовать метод filter, который так же вызывает функцию для каждого элемента, но в новом массиве будут только те элементы, при которых функция, которую мы передали как аргумент в filter, вернула true

На простом примере

const nums = [1, 2, 3, 4, 5];
const numsLessThan3 = nums.filter( n => n < 3 );
// numsLessThan3 = [1, 2];

На вашем примере

cell(numX, numY) {
  return this.cells.filter((cell) =>
      numX == cell.opts.numX &&
      numY == cell.opts.numY
  )[0]; 
  // [0], так как нам нужен только первый элемент,
  // подразумевается что он всегда будет один
}

UPDATE

Если хотите оптимизировать кода, то тогда воспользуйтесь циклом

cell(numX, numY) {
  let neededCell = null
  const {length} = this.cells
  for(let i = 0; i < length; i++) {
      const cell = this.cells[i]
      if (numX == cell.opts.numX && numY == cell.opts.numY) {
          neededCell = cell
          break // выйдет из цикла
          // либо можно сразу return cell
          // без break и neededCell = cell
      }
  }
  return neededCell
}
READ ALSO
если js отключен, подключаем php

если js отключен, подключаем php

Вообщем суть такая, на сайте ведутся логи, js определяет разрешение экрана и отправляет обработчику на php, который заносит в логи все данные...

431
дожидаться выполнения Ajax [дубликат]

дожидаться выполнения Ajax [дубликат]

На данный вопрос уже ответили:

382
Yii2 ActiveForm submit

Yii2 ActiveForm submit

У меня есть 2 формы одна обычная

563
Вызов JS функции из WebView выдаёт ошибку &ldquo;function is not defined&rdquo;

Вызов JS функции из WebView выдаёт ошибку “function is not defined”

При попытке вызвать функцию MyApp_HighlightAllOccurencesOfString() из WebView

359