Подтвердить что ты не робот

ES6 - объявить прототип метода для класса с оператором импорта

Я использую классы ES6. Я хочу иметь возможность сделать это:

function Car(color) {
  this.color = color;
};

Car.prototype.getColor = require('./getColor');

Где получить цвет - экспортированная функция. т.е. я хочу иметь возможность импортировать функцию из внешнего файла, а набор - как прототип метода в классе ES6. Это тот тип синтаксиса, о котором я говорю:

class Car {
  constructor(color) {
    this.color = color;
  }

  getColor() {} // I want to import this function from './getColor', as above
}

Это выполнимо?

4b9b3361

Ответ 1

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

Поскольку вы хотите использовать ES6, я буду использовать импорт ES6.

Минимальное усилие, используя прототип:

import getColor from 'path/to/module';

class Car {
    ...
}

Car.prototype.getColor = getColor;

Как вы можете видеть, вы все еще используете свойство prototype для присоединения метода, если хотите.


Вызов модуля внутри метода класса:

В качестве альтернативы, если вы не хотите использовать свойство prototype, вы всегда можете вернуть свой метод из модуля:

import getColor from 'path/to/module';

class Car {
    getColor () {
        return getColor.call(this);
    }
}

Использование Getter

Вы также можете быть немного сложнее и использовать "getter" для достижения этого по-другому.

import getColor from 'path/to/module';

class Car {
    get getColor () { return getColor.bind(this) }
}

Затем вы можете использовать его, просто позвонив myInstanceOfCar.getColor()

Или в более семантическом использовании геттера:

class Car {
    get color () { return getColor.call(this) }
}

// ...

const color = myInstanceOfCar.color;

Имейте в виду, что getters/setters не могут иметь то же имя, что и свойства, заданные в конструкторе. В конечном итоге вы превысите максимальный стек вызовов с бесконечной рекурсией, когда вы попытаетесь использовать установщик для установки того же свойства. Пример: set foo (value) { this.foo = value }


Свойства класса ES2016

Если вы используете Babel для пересылкис использованием экспериментальных предложений), и хотите используйте ES2016, вы можете использовать следующий синтаксис (но имейте в виду, что это относится к методу непосредственно к объекту и не устанавливает его на прототипе):

import getColor from 'path/to/module';

class Car {
    getColor = getColor;
}

Необязательное связывание с свойствами класса

Если вы используете стенографию ES7 для установки свойства, вам не нужно связывать метод (настройка как свойство изменяется, к которому относится "this", по существу автоматически привязывая его), но вы, безусловно, можете, если вы захотите (например, если вы хотите связать что-то еще):

getColor = getColor.bind(this);

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

getColor = this::getColor; // or just "::getColor" if binding to its current value

Ответ 2

Да. Синтаксис class - это просто (очень сложный) синтаксический сахар для функций конструктора. Итак, Car по-прежнему будет функцией с свойством prototype, и вы можете сделать то же самое:

import getColor from './getColor';
// ...
Car.prototype.getColor = getColor;

Однако это делает метод перечислимым, в отличие от методов, созданных из синтаксиса класса. Таким образом, вы можете использовать Object.defineProperty вместо этого.

Ответ 3

Если вам интересно, я разработал небольшой модуль для привязки функций с различным количеством параметров к методам класса: https://github.com/ngryman/to-method.

const toMethod = require('to-method');

function Car(color) {
  this.color = color;
}

toMethod(Cat, { getColor: require('./getColor') });