Какой смысл реализации обратного вызова внутри объявления функции? - PullRequest
0 голосов
/ 29 июня 2019

В книге Eloquent Javascript, в главе 6 есть следующий пример:

class Matrix {
  constructor(width, height, element = (x, y) => undefined) {
    this.width = width;
    this.height = height;
    this.content = [];

    for (let y = 0; y < height; y++) {
      for (let x = 0; x < width; x++) {
        this.content[y * width + x] = element(x, y);
      }
    }
  }

 //...
}

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

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

const test = new Matrix(2, 4, () => console.log('hello'));

Так какой смысл реализовывать обратный вызов, являющийся параметром функции? Может ли читатель определить, сколько параметров будет передано в обратный вызов?

Ответы [ 4 ]

2 голосов
/ 29 июня 2019

Если вы не укажете третий параметр, значением по умолчанию element будет (x, y) => undefined.

Пожалуйста, обратитесь к этой MDN ссылка . Это даст некоторое представление. Надеюсь, это поможет.

1 голос
/ 29 июня 2019

Что пример делает с element, это устанавливает значение по умолчанию.В этом случае значение по умолчанию ничего не делает.

Обратите внимание, что вы также можете использовать ()=>{} в качестве элемента по умолчанию, оно будет работать в JavaScript, так как язык не проверяет количество аргументов при вызове функции(но это может привести к ошибке проверки типа в TypeScript).

Это распространенный шаблон: вместо использования undefined или null вы помещаете параметр по умолчанию, который ничего не делает, поэтому в кодеВам не нужно проверять, определено ли element перед вызовом функции.См .: https://en.wikipedia.org/wiki/Null_object_pattern

Некоторые библиотеки, такие как lodash, также включают константы, такие как noop, определенные как пустая функция, поэтому вы можете написать код в виде:

const noop = ()=>{}

class Matrix {
  constructor(width, height, element = noop) {
//...  
  }
}

Дополнительная информация:

Конструктор Matrix, кажется, инициализирует одно измерение Array для хранения матрицы.Вы можете заменить этот вложенный цикл for на Array.from.Что-то вроде:

this.contents = Array.from(
  {length: height * width},
  n => element(n % width, Math.floor(n/height))
);

Я не проверял математику, поэтому в примере могут быть ошибки индекса.Смотри: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

0 голосов
/ 29 июня 2019

Этот класс имеет 3 параметра, применяемых к «Конструктору».

Третья функция обратного вызова с именем «element» является необязательной и имеет значение по умолчанию «(x, y) => undefined». Поэтому, если вы не передали третий аргумент при создании нового экземпляра класса «Матрица», он будет по умолчанию.

если вы передаете определенную функцию здесь (например)

let myMatrix = new Matrix(100,100,(x,y) => x * y);

на данном этапе

this.content[y * width + x] = element(x, y);

возвращает соответствующие значения в соответствующие слоты массива свойства this.content вашего нового экземпляра Matrix.

Таким образом, ваша матрица будет иметь такое свойство «содержимого» (например):

myMatrix.content[0] = 0;
myMatrix.content[1] = 0;
...
myMatrix.content[101] = 1;
myMatrix.content[102] = 2;
// and so on

В противном случае, если вы не передадите какую-либо функцию при создании нового экземпляра, всем сгенерированным слотам массива свойства "this.content" будут присвоены неопределенные значения из-за значения свойства по умолчанию

(x, y) => не определено

0 голосов
/ 29 июня 2019

Насколько я понимаю, это просто дополнительный инициализатор. Если вы назовете его как-то типа () = > 0, ваша матрица будет инициализирована с 0 вместо undefined. (x,y) => x === y ? 1 : 0 будет производить единичную матрицу. и т.д ....

(обновить после прочтения главы) Это подтверждается предложением после примера в книге:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...