Добавление метода к методу класса в машинописном тексте (javascript)

Я хочу добавить метод к методу:

class MyClass {
    public foo(text: string): string {
        return text + ' FOO!'
    }

    // Some magical code which adds the method `bar` to `foo`.
}

const obj = new MyClass();
console.info(obj.foo('thing'));
console.info(obj.foo.bar('other thing'));

Это возможно? Я нашел аналогичный случай для функций:

function Sum(x: number) { /*...*/ }
namespace Sum {
    export function empty() { /*...*/ }
}

Есть ли способ сделать то же самое с методами класса?

Я бы хотел, чтобы код в классе не обновлялся после создания объекта.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
0
81
3

Ответы 3

Не совсем то, о чем вы просите, но конечный результат работает:

class MyClass {
  public foo: MyChildClass = new MyChildClass();
}

class MyChildClass {
  public bar(text: string): string{
    return text;
  }
}

const obj = new MyClass();
console.info(obj.foo.bar('thing'));

РЕДАКТИРОВАТЬ Прочитал ваш ответ на свой комментарий. Я думаю, что более простой способ достичь вашей цели - использовать такие параметры по умолчанию, как:

function foo(text: string, snapshot = false): string{
  if (snapshot){
    return 'snapshot';
  }
  return text;
}

console.debug(foo('test'));
console.debug(foo('test', true));

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

interface iFooArgs{
  text: string;
  bypass?: boolean;
  snapshot?: boolean;
}

function foo(args: iFooArgs): string {
  if (args.bypass){
    return 'bypass';
  }
  if (args.snapshot){
    return 'snapshot';
  }
  return args.text;
}

console.debug(foo({text: 'test'}));
console.debug(foo({text: 'bypass?', bypass: true}));
console.debug(foo({text: 'snapshot?', snapshot: true}));
foo - это метод - это основа того, чего я хочу достичь. Я хочу, чтобы метод foo() использовался по умолчанию. Это может быть метод доступа к дорогостоящим ресурсам со встроенным кешированием. Вам может понравиться альтернативный способ использования этого метода, например, обход или аннулирование кеша. Возможно, вы обычно используете obj.fetch('42'), но иногда вам может понадобиться obj.fetch.bypass('42') для принудительной загрузки дорогостоящих ресурсов или obj.fetch.snapshot('42') для принудительного использования кеша, даже если тайм-аут кеша истек. В python я бы просто использовал ваш пример с __call__(self).
André C. Andersen 05.10.2018 22:44

@ AndréC.Andersen Это интересно. Я думаю, что в js это обычно делается просто так, чтобы foo включал параметр для обхода кеша. Потребители foo, которые не предоставляют параметр «bypass cache», получат кеш. foo () сама проверит, были ли предоставлены параметры, или "undefined" по умолчанию для вашего "использования по умолчанию".

Guillaume CR 09.10.2018 17:35

@ AndréC.Andersen Добавил к моему ответу то, что я считаю более простым решением вашей проблемы.

Guillaume CR 09.10.2018 17:41

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

class MyClass {
  constructor(myName) {
    this.myName = myName
    this.constructor.prototype.foo.bar = (function(a) {
      console.info(this.myName, "calling foo.bar with:", a)
    }).bind(this)
  }
  foo(text) {
    return text + ' FOO!'
  }

}

const obj = new MyClass("Mark");
obj.foo.bar('thing')
console.info(obj.foo('test'))

Обновлено: Это можно решить чисто с помощью типы пересечений:

class MyClass {

    constructor() {
        this.foo = function () {
            return "this is a"
        };

        this.foo.bar = function() {
            return "this is b"
        };
    }

    public foo: Function & { bar?: () => string };
}

const obj = new MyClass();

console.info(obj.foo());
console.info(obj.foo.bar());

Протестируйте его в игровой группе Typescript

Это возможно, потому что при использовании знака & в определении типа метода класса мы являемся возня вместе как типом Function, так и простым типом объекта, который имеет 1 свойство bar, которое является другой функцией. Однако это свойство должно быть объявлено как необязательное во втором типе, потому что Typescript будет жаловаться на то, что в первом назначении внутри конструктора класса он не удовлетворяет этому дополнительному типу. Но на самом деле следующее выражение в конструкторе завершает его, присваивая свойство bar функции foo.

--- СТАРЫЙ ответ следует, не используйте его, он не делает именно то, что хотел OP

Вместо метода определите метод доступа геттера для члена класса 'foo', который возвращает объект с функцией 'bar'.

    class MyClass {
        get foo(): {bar: (text: string) => string} {

            // run any code here that needs to be run before bar()

            return {
                bar: (text: string) => {
                    return text + ' FOO!';
                }
            }
        }
    }

    const obj = new MyClass();
    console.info(obj.foo.bar('thing'));

Похоже, что foo() больше не является вызываемой функцией. Есть ли способ сделать что-то подобное, но при этом позволить obj.foo() работать?

Mark 05.10.2018 19:28

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