Разрешение пользователям изменять импортированные функции модуля ES6 в контексте - PullRequest
0 голосов
/ 06 ноября 2018

Я немного запутался, если что-то возможно или нет.

Я создаю модуль, который содержит следующее:

export function logText(){
    console.log('some text');
}

export class Example {
    constructor(){
        logText();
    }
}

Цель состоит в том, чтобы пользователь вызвал new Example для запуска логики модуля.

import { logText, Example } from 'example';

// Do some magic here to modify the functionality of logText

new Example();

Возможно ли конечному пользователю изменить logText?

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

Я часто вижу репозитории с множеством экспортированных функций, которые бесполезны, и пользователям не приходится переделывать практически все функции вручную, что делает его довольно бессмысленным. Один хороший пример - это хранилище , где они даже называют экспортированные функции их «API». В этом примере это довольно бессмысленный экспорт, и в худшем случае он вызовет проблемы, если кто-то попытается использовать их вместе с основной функцией. Но если бы вы могли изменить их и сделать так, чтобы они продолжали работать, это имело бы смысл для меня.

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Учитывая это:

import { logText, Example } from 'example';

Возможно ли конечному пользователю изменить logText?

Поскольку вы не очень точно понимаете, что вы имеете в виду под "изменить logText", я рассмотрю несколько вариантов:

Можете ли вы переназначить какую-либо другую функцию на переменную logText?

Нет. Тебе этого не сделать. Когда вы используете import, создается переменная const, которой нельзя присвоить. Даже если это не const, это просто локальный символ, который в любом случае не повлияет на использование другим модулем logText(). Механизм import разработан таким образом специально. Предполагается, что загрузчик вашего модуля не сможет заменить внутренние части реализации модуля, которые не были специально предназначены для замены.

Можно ли изменить код внутри функции logText снаружи модуля, в котором она содержится?

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

Можете ли вы заменить функцию logText() внутри модуля так, чтобы реализация Example внутри этого класса использовала вашу функцию logText()?

Нет, вы не можете сделать это снаружи модуля. Вы должны будете на самом деле изменить сам код модуля, или кто-то должен будет разработать интерфейс Example, чтобы иметь заменяемую или модифицируемую функцию logText(), которую использовал объект Example.

Например, logText() можно сделать методом в Example, а затем вы можете переопределить его своей собственной реализацией, что приведет к тому, что реализация Example будет использовать ваше переопределение.

Код в модуле, который вы не изменяете:

export class Example {
    constructor(){
        this.logText();
    }
    logText() {
        console.log('some text');
    }
}

Код, выполняющий импорт:

import { Example } from 'example';

class MyExample extends Example {
    constructor() {
        super();
    }
    logText() {
        console.log("my own text");
    }
}

let o = new MyExample();    

Можете ли вы создать собственную версию logText и использовать ее локально?

Конечно, вы можете сделать это.

function myLogText() {
    do your own thing
}

И вы даже НЕ можете импортировать logText, чтобы вы могли использовать имя символа logText() локально, если хотите. Но это никак не повлияет на то, что делает Пример.

Существуют ли способы разработки примера модуля, чтобы можно было легко заменить logText().

Да, есть много способов сделать это. Я показал выше, что делает logText метод, который можно переопределить. Он также может быть передан в качестве необязательного аргумента конструктору Example.

Может даже быть экспортированный объект, который позволил бы вызывающей стороне заменить свойства этого объекта. Например:

export const api = {
    logText: function logText(){
        console.log('some text');
    }
};

export class Example {
    constructor(){
        api.logText();
    }
}

Затем используйте это так:

import { api, Example } from 'example';

api.logText = function() {
    console.log('my Text');
};

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

0 голосов
/ 06 ноября 2018

Возможно ли конечному пользователю изменить logText?

Нет, это невозможно, import привязки являются неизменяемыми, а функциональные объекты в основном неизменяемы по коду, который они содержат.

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

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

export class Example {
    constructor(log=logText){
        log();
    }
}
...