Клонирование объекта javascript с обратным вызовом не выполняет метод обратного вызова

#javascript

#javascript

Вопрос:

У меня есть компонент, в котором я определяю два объекта со свойствами по умолчанию, один из которых является методом обратного вызова.

Затем я пытаюсь клонировать / назначить этот объект по умолчанию другой переменной, которую использует мой получатель. Однако при этом метод обратного вызова никогда не запускается при нажатии кнопки, к которой он подключен.

object.assign И spread то, и другое я тоже пытался, но, возможно, я неправильно подхожу к этому.

Пример кода:

 // defaults
DEFAULT_SAVE_HANDLER = {
    cb: this._modalSaveHandler,
    label: "Create Case",
    variant: "brand",
    action: "createcase",
    class: "",
    disabled: true,
    visible: true
  };
  DEFAULT_CANCEL_HANDLER = {
    cb: this._modalCancelHandler,
    label: "Cancel",
    variant: "netrual",
    class: "btn-left",
    action: "close",
    disabled: false,
    visible: true
  };

  // Set vars for getter
  _save = this.DEFAULT_SAVE_HANDLER;
  _cancel = this.DEFAULT_CANCEL_HANDLER;

  /* Spread Attempt
  _save = { ... this.DEFAULT_SAVE_HANDLER };
  _cancel = { ... this.DEFAULT_CANCEL_HANDLER};
  */

 /* Assign Attempt
  _save = Object.assign({}, this.DEFAULT_SAVE_HANDLER);
  _cancel = Object.assign({}, this.DEFAULT_CANCEL_HANDLER);
  */


  // Getters
  get saveHandler() {
    return this._save
  }
  set saveHandler(props){
    this._save = Object.assign({}, this.DEFAULT_SAVE_HANDLER, props)
  }

  get cancelHandler() {
    return this._cancel
  }
  set cancelHandler(props) {
    this._cancel = Object.assign({}, this.DEFAULT_CANCEL_HANDLER, props)
  }


  // Callbacks
  _modalSaveHandler = () => {
    console.log("save handler ran");
  };

  _modalCancelHandler = () => {
    console.log("cancel handler ran");
  };

  // Some random method to update a property on the button
  onButtonClick(){
      this.saveHandler = { disabled: false };
  }
  

Теперь, когда мой другой компонент пытается запустить метод обратного вызова, который я пытаюсь передать, он вообще не попадает в него.

Это проблема с областью действия или мое непонимание того, как клонируются / ссылаются на свойства?

Обновить:

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

Похоже, проблема возникает при попытке ссылаться на метод обратного вызова, а не на встроенный.

 DEFAULT_CANCEL_HANDLER = {
    //cb: this._modalCancelHandler,
    cb: () => {
      console.log('this works')
    },
    label: "Cancel",
    variant: "netrual",
    class: "btn-left",
    action: "close",
    disabled: false,
    visible: true
  };
  

Комментарии:

1. Сомневаюсь, что это имеет какое-либо отношение к клонированию. Возможно, вам нужно изменить ваши обратные вызовы на cb: this._modalSaveHandler.bind(this)

2. Хм, спасибо @Phil, я попробовал, но он выдал ошибку Cannot read property 'bind' of undefined .

Ответ №1:

Вам нужно использовать геттер, если вы хотите ссылаться на ключи объекта, который вы только что объявили.

Без средства получения обработчик исходного объекта уже не определен, следовательно, он не клонируется.

 const obj = {
  _handler() {
    console.log('foo')
  },
  get handler() {
    return this._handler
  }
}

const clone = { ...obj }

obj.handler()

clone.handler()  

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

Комментарии:

1. Таким образом, это работает, если функция определена непосредственно в свойстве следующим образом: _cb: () => { console.log('blah') }, get cb() { return this._cb } . Но почему я не могу ссылаться на функцию fat arrow из свойства и заставить ее работать таким же образом, например cb: this._modalSaveHandler ?

2. Функции со стрелками не переносят this так же, как обычные функции. «Попытка использовать функцию arrow в таких классах, как, например, компоненты vue, является распространенной ошибкой. Или теперь в вашем случае это та же ошибка. Как правило, всякий раз, когда вы работаете this , просто держитесь подальше от функций arrows и в этом случае обезопасьте себя от головной боли из-за синтаксиса. Я нашел некоторую статью об этом с помощью быстрого поиска в Интернете dev.to/shubham57396755/arrow-functions-and-this-keyword-1kg7

Ответ №2:

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

Попробуйте переместить объявление обратного вызова выше, чем DEFAULT_SAVE_HANDLER и DEFAULT_CANCEL_HANDLER

Нравится:

   // Callbacks
  _modalSaveHandler = () => {
    console.log("save handler ran");
  };

  _modalCancelHandler = () => {
    console.log("cancel handler ran");
  };

  // defaults
  DEFAULT_SAVE_HANDLER = {
    cb: this._modalSaveHandler,
    label: "Create Case",
    variant: "brand",
    action: "createcase",
    class: "",
    disabled: true,
    visible: true
  };
  DEFAULT_CANCEL_HANDLER = {
    cb: this._modalCancelHandler,
    label: "Cancel",
    variant: "netrual",
    class: "btn-left",
    action: "close",
    disabled: false,
    visible: true
  };

  //....
  

Комментарии:

1. Можете ли вы объяснить, почему это будет работать? Разве функции обратного вызова уже не были бы подняты на вершину? Тот факт, что это работает, просто побуждает меня спросить, почему.

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