Как получить ссылку на функцию класса в ES6?

Извините, если вопрос слишком простой, но я что-то здесь упускаю. Просто переключил модуль ES5, который выглядел так:

module.exports = {
  func1: function(a, b) {...},
  func2: function(a, b) {...}
};

К классу ES6, который выглядит так:

export default class {
  func1(a, b) {...}
  func2(a, b) {...}
}

И все было хорошо: в обоих случаях я мог export mod from 'module'; и звонить mod.func1(a, b) и mod.func2(a, b).

Однако у меня есть функция, которая получает функцию модуля для вызова:

var caller = function(func, val1, val2) {
  let a = something(val1);
  let b = something(val2);
  return func(a, b);
};

Когда я вызываю caller(mod.func1, x, y), я получаю желаемый результат с первой реализацией, но undefined is not a function со второй.

Распечатка значения mod.func1 возвращает [Function] в обоих случаях, но явно что-то еще возвращается из класса ES6.

Что я делаю неправильно и как мне получить функцию класса, которую я могу вызвать в другой функции?

Обновление: во второй реализации я забыл добавить код создания экземпляра:

import Mod from 'module';
var mod = new Mod();

person Traveling Tech Guy    schedule 01.08.2015    source источник
comment
Я очень сомневаюсь, что mod.func1(a, b) работает с экспортированным классом.   -  person Bergi    schedule 02.08.2015
comment
Забыл код создания экземпляра - теперь добавил. Спасибо.   -  person Traveling Tech Guy    schedule 02.08.2015
comment
Хм, передача метода mod.func1 как функции в другое место требует, чтобы вы имели дело с this контекст в обратных вызовах проблема, но это также не должно меняться при переключении с объекта на экземпляр класса. Можете ли вы показать нам тело вашей функции?   -  person Bergi    schedule 02.08.2015


Ответы (2)


class MyClass {
  method(args) {}
}

это короткая рука для:

function MyClass() {}
MyClass.prototype.method = function(args){};

То, что вы ищете, - это метод static в конструкторе, который в ES{3,5} делается следующим образом:

function MyClass() {}
MyClass.method = function(args){};

а в ES6 это делается с модификатором static:

export default class {
  static func1(a, b) { /* stuff */ }
  static func2(a, b) { /* stuff */ }
}

Однако вы можете использовать сокращенные методы даже в объекте, поэтому в общем случае использование обычного объекта более понятно:

export default {
  func1(a, b) {/* stuff */},
  func2(a, b) {/* stuff */}
}

Почему в конструкторе недоступны методы прототипа?

Потому что это не так в ES3 или ES5:

function MyClass() {};
MyClass.prototype.method = function(args) {};

MyClass.method  // undefined

var instance = new MyClass();
instance.method  // function(args) {}

Создание экземпляра необходимо для доступа к методам прототипа.

person Sean Vieira    schedule 01.08.2015
comment
Спасибо за предложение. Но если class это просто сахар, то почему такая разница в доступности функций? - person Traveling Tech Guy; 02.08.2015
comment
Спасибо, Шон. Я обновил свой вопрос, чтобы показать код создания экземпляра, но это тоже не сработало :(. Кстати, если вы хотите вызвать метод для имени класса, вы можете добавить static в определение функции. - person Traveling Tech Guy; 02.08.2015
comment
Правильно - я не могу воспроизвести это в Babel - я получаю ожидаемое поведение, когда создаю экземпляр класса. Любые дополнительные сведения о том, как вы компилируете/запускаете это (или может помочь более подробный фрагмент). - person Sean Vieira; 02.08.2015
comment
Я использую Babel для транспиляции, и у меня возникла проблема с передачей функции класса в промежуточное ПО Passport. Код слишком сложен для публикации. Но вы говорите, что вам удалось заставить работать пример, подобный моему? Если да, то это должно быть что-то, что я сделал неправильно. - person Traveling Tech Guy; 02.08.2015

Почему вы перешли на конструкцию class (что чуть больше, чем синтаксический сахар для конструктора и прототипа с методами)? Нет никаких причин не использовать литерал объекта, как вы это делали раньше — вы также можете использовать синтаксис метода:

export default {
  func1(a, b) {...},
  func2(a, b) {...}
};

Вместо того, чтобы экспортировать объект "статическими" методами, здесь было бы разумнее использовать именованные экспорты:

export function func1(a, b) {...}
export function func2(a, b) {...}

который вы можете импортировать с помощью import * as mod from 'module', если хотите использовать mod в качестве пространства имен.

person Bergi    schedule 01.08.2015
comment
Я не понимаю, почему все думают, что должны использовать как можно больше функций ES6, даже если это не имеет смысла. То же самое для стрелочных функций... и вдруг это не работает, как ожидалось. - person Felix Kling; 02.08.2015
comment
У меня нет проблем с тем, что он не работает - я хочу понять, почему он не работает. - person Traveling Tech Guy; 02.08.2015