ES6: переопределение экспортируемой функции

#javascript #ecmascript-6 #es6-modules

#javascript #ecmascript-6 #es6-модули

Вопрос:

Учитывая стороннюю библиотеку, которая экспортирует функцию и использует эту функцию в своей внутренней логике — есть ли какой-либо способ переопределить эту функцию? Например:

third-party.js

 export function a() {
 console.log('a');
}

export function b() {
 a();
}
  

my-module.js

 import * as tp from 'third-party';

//Re-define, something like this
Object.defineProperty(tp, 'a', { writable: true, value: () => console.log('c')});

//Call b and get the re-define function called
tp.b(); //Expected output: 'c'
  

Несколько основных моментов:

  • Мне это нужно не для тестирования, а для производства (да, я знаю, что это был бы грязный взлом)
  • Да, я знаю, что импорт представляет собой просмотры только для чтения в реальном времени, я ищу обходной путь для преодоления этого ограничения
  • Нет, я не могу изменить код сторонней библиотеки
  • Мне нужно мое изменение, чтобы фактически изменить логику третьей стороны. Я хотел бы вызвать функцию, которая вызывает, a а не a саму себя.

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

1. Нет, это невозможно сделать без исправления кода (что может быть возможно с помощью скрипта), если a() ссылка на вызов относится к локальной a переменной.

2. В какой среде это выполняется? Вы используете пользовательский загрузчик, пакет или что-то в этомроде?

3. Нет, это чистая среда узла. Однако у меня есть определенная степень гибкости для моего скрипта. Это означает, что я мог бы объединить ее (чего я сейчас не делаю).

4. Вы можете попробовать поэкспериментировать с github.com/elastic/require-in-the-middle

Ответ №1:

Экспортируемый модуль доступен только для чтения. Итак, вы не можете этого сделать.

 delete tp.a;
tp.a = () => {
  console.log('c')
}
tp.a() // 'c'
tp.b() // You'll still get 'a'
// it's because, b is calling exported function a
  

Если вы хотите, tp.b() чтобы значение было переопределено, тогда вы не экспортируете их, а вызываете экземпляр. В вашем примере кода просто a не b экспортируйте. Но поскольку вы пытаетесь переопределить ее из сторонней библиотеки. Это невозможно сделать.

Но если вы настаиваете на их использовании, тогда вы должны переопределить обе функции.

 const obj = {...tp}
obj.a = () => {
  console.log('c')
}

obj.b() // 'a'

obj.b = () => {
  obj.a()
}

obj.b() // 'c'
  

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

1. Я попробовал это, и это не сработало. Проблема здесь заключается в экспорте, а не в присвоении объекту. Вопрос конкретно касается экспорта.

2. Я внес небольшую модификацию , чтобы соответствовать вопросу, и это не работает. Я бы хотел вызвать, b а не a . Извините, но ваш ответ не отвечает на вопрос.

3. Обновил мой ответ. То, что вы ищете, невозможно.