JavaScript - Передача функции обратного вызова внутри функции, вызывающей себя

Я пытаюсь передать callback функция внутри self-invoking function в JavaScript, но я получаю "неопределенный", когда done Функция выполнена.

Я прочитал этот ответ, чтобы написать этот код ниже:

function done() {
    console.log(dateFilter.getI());
    console.log(dateFilter.getF());
}

var dateFilter = (function(callback) {
    var _dInicio = new Date(), _d = new Date(),
        _dFim = new Date(_d.setMonth(new Date().getMonth() - 1));
    return {
        getI: function() { return _dInicio; },
        getF: function() { return _dFim; },
        setI: function(d) { _dInicio = d; },
        setF: function(d) { _dFim = d; }
    }, callback();

 })(done);

Может быть, я неправильно использую оператор запятой, но я думаю, что это должно работать. Кто-то может указать мне, где я что-то неправильно понимаю?

3 ответа

Вы звоните done функция после return Дальше, ты не сдаешь парам dateFilter,

return { -> return before calling callback `function`.
    getI: function() { return _dInicio; },
    getF: function() { return _dFim; },
    setI: function(d) { _dInicio = d; },
    setF: function(d) { _dFim = d; }
}, callback( );
            ^
            |_ Calling callback without param `dateFilter`

Посмотрите на этот фрагмент кода

function done(dateFilter) {
  console.log(dateFilter.getI());
  console.log(dateFilter.getF());
}

(function(callback) {
  var _dInicio = new Date(),
    _d = new Date(),
    _dFim = new Date(_d.setMonth(new Date().getMonth() - 1));

  callback({
    getI: function() {
      return _dInicio;
    },
    getF: function() {
      return _dFim;
    },
    setI: function(d) {
      _dInicio = d;
    },
    setF: function(d) {
      _dFim = d;
    }
  });

})(done);

Увидеть? сейчас печатает значения.

Две причины этого не могут работать:

  • Вы возвращаете результат callback с оператором запятой, но done ничего не возвращает
  • Вы пытаетесь использовать dateFilter во время инициализации IIFE dateFilter - ему еще не присвоено возвращаемое значение

Нет абсолютно никаких причин использовать обратный вызов с IIFE. Просто пиши

var dateFilter = (function() {
    var _dInicio = new Date(), _d = new Date(),
        _dFim = new Date(_d.setMonth(new Date().getMonth() - 1));
    return {
        getI: function() { return _dInicio; },
        getF: function() { return _dFim; },
        setI: function(d) { _dInicio = d; },
        setF: function(d) { _dFim = d; }
    };
}());

console.log(dateFilter.getI());
console.log(dateFilter.getF());

Ты действительно близко. Ваше предположение об операторе запятой верно. И я думаю, что есть лучший способ подключить done() обратный вызов, так что код немного более устойчив, и порядок, в котором все происходит, немного яснее.

Во-первых, давайте посмотрим на return заявление. Все операторы return делают две вещи (оценивают возвращаемое значение, затем возвращают его), но из-за запятой этот выполняет три в следующем порядке:

  1. Оценка литерала объекта { getI:... }
  2. оценки callback(), что означает вызов callback()
  3. возвращая возвращаемое значение callback(), так как оператор запятой возвращает свой второй операнд.

Итак, обратите внимание, что callback() на самом деле вызывается до того, как ваша функция возвращается, поэтому это происходит до dateFilter имеет значение. (И даже если бы оно имело значение, это было бы возвращаемое значение из callback(), который не определен.)

И я думаю, что здесь есть еще один аспект вашего кода, который, я думаю, стоит посмотреть. Обратные вызовы обычно принимаютпараметры. Самый простой способ думать об этом: вместо того, чтобы возвращать значение, вы передаете его обратному вызову.

В общем, код легче читать и отлаживать, если вы передаете параметры вместо побочных эффектов общих переменных.

Я только что сделал одно изменение в вашем коде, и он работает:

function done(dateFilter) {
    console.log(dateFilter.getI());
    console.log(dateFilter.getF());
}

(function(callback) {
    var _dInicio = new Date(), _d = new Date(),
        _dFim = new Date(_d.setMonth(new Date().getMonth() - 1));
    callback({
        getI: function() { return _dInicio; },
        getF: function() { return _dFim; },
        setI: function(d) { _dInicio = d; },
        setF: function(d) { _dFim = d; }
    });

 })(done);

Итак, что я сделал?

  • Вместо побочных эффектов dateFilter значение, я передаю это непосредственно callback,

Это означает, что в return заявление, и нет необходимости побочных эффектов dateFilter глобальное значение. (dateFilter теперь параметр для done isntead.)

Я надеюсь, что это проясняет ситуацию для вас. Ура!

Другие вопросы по тегам