При создании класса в CoffeeScript следует ли определять все методы экземпляра с помощью =>
оператора ("жирная стрелка"), а все статические методы - с помощью ->
оператора?
coffeescript
arrow-functions
Али Салехи
источник
источник
Ответы:
Нет, я бы не использовал это правило.
Основной вариант использования, который я нашел для жирной стрелки при определении методов, - это когда вы хотите использовать метод в качестве обратного вызова, и этот метод ссылается на поля экземпляра:
Как видите, вы можете столкнуться с проблемами при передаче ссылки на метод экземпляра в качестве обратного вызова, если вы не используете жирную стрелку. Это связано с тем, что жирная стрелка привязывает экземпляр объекта к,
this
а тонкая стрелка - нет, поэтому методы тонкой стрелки, называемые обратными вызовами, как указано выше, не могут получить доступ к полям экземпляра, например,@msg
или вызвать другие методы экземпляра. Последняя строка - это обходной путь для случаев, когда использовалась тонкая стрелка.источник
this
, которая будет вызываться из тонкой стрелки, а также переменные экземпляра, которые вы получите с помощью жирной стрелки?this
установлена на переменную, которую я хочу использовать. Однако я также хочу сослаться на метод класса, поэтому я хочуthis
также сослаться на класс. Я могу выбрать только одно присвоение дляthis
, так как лучше всего использовать обе переменные?Точка, не упомянутая в других ответах, которую важно отметить, заключается в том, что связывание функций жирной стрелкой, когда в этом нет необходимости, может привести к непредвиденным результатам, таким как в этом примере с классом, который мы просто назовем DummyClass.
В этом случае функции делают именно то, что и следовало ожидать, и использование жирной стрелки, похоже, без потерь, но что происходит, когда мы модифицируем прототип DummyClass после того, как он уже определен (например, изменение какого-либо предупреждения или изменение вывода журнала) :
Как мы видим, переопределение нашей ранее определенной функции прототипа приводит к тому, что some_function корректно перезаписывается, но other_function остается неизменной в экземплярах, поскольку жирная стрелка заставляет other_function из класса связываться со всеми экземплярами, поэтому экземпляры не будут ссылаться на свой класс. найти функцию
Даже толстая стрелка не будет работать, поскольку толстая стрелка только приводит к привязке функции к новым экземплярам (которые, как и следовало ожидать, получают новые функции).
Однако это приводит к некоторым проблемам: что, если нам нужна функция (например, в случае переключения функции ведения журнала на окно вывода или что-то еще), которая будет работать на всех существующих экземплярах (включая обработчики событий) [как таковые мы не можем использовать толстые стрелки в исходном определении], но нам все еще нужен доступ к внутренним атрибутам в обработчике событий [точная причина, по которой мы использовали толстые стрелки, а не тонкие стрелки].
Ну, самый простой способ сделать это - просто включить две функции в исходное определение класса, одну из которых определяют с помощью тонкой стрелки, которая выполняет операции, которые вы хотите выполнить, а другую - с помощью жирной стрелки, которая ничего не делает, кроме вызова первой функции. например:
Поэтому, когда использовать тонкие / толстые стрелки, можно довольно просто подвести итог четырьмя способами:
Тонкие стрелки в одиночку должны использоваться, когда выполняются оба условия:
Функции только жирной стрелки следует использовать при выполнении следующего условия:
Функция толстой стрелки, которая напрямую вызывает функцию тонкой стрелки, должна использоваться при соблюдении следующих условий:
Функция тонкой стрелки, которая напрямую вызывает функцию жирной стрелки (не показана), должна использоваться при соблюдении следующих условий:
Во всех подходах следует учитывать случай, когда функции прототипа могут быть изменены, будет ли поведение определенных экземпляров вести себя правильно, например, хотя функция определена жирной стрелкой, ее поведение может быть непоследовательным в экземпляре, если она вызывает метод, измененный в прототипе
источник
Обычно
->
это нормально.Обратите внимание, как статический метод возвращает объект класса для,
this
а экземпляр возвращает объект экземпляра дляthis
.Происходит то, что синтаксис вызова обеспечивает значение
this
. В этом коде:foo
bar()
по умолчанию будет контекстом функции. Так что все работает так, как вы хотите. Толстая стрелка нужна вам только тогда, когда вы вызываете эти функции другим способом, который не использует точечный синтаксис для вызова.В обоих случаях использование жирной стрелки для объявления этой функции позволит им работать. Но если вы не делаете что-то странное, вам обычно это не нужно.
Так что используйте
->
до тех пор, пока вам действительно не понадобится,=>
и никогда не используйте=>
по умолчанию.источник
x = obj.instance; alert x() == obj # false!
=>
он может понадобиться в статических методах / методах экземпляра класса.// is not a CoffeeScript comment
тогда как# is a CoffeeScript comment
.setTimeout foo.bar, 1000
"делать это неправильно"?setTimeout (-> foo.bar()), 1000
ИМХО использовать жирную стрелку намного приятнее, чем использовать .setTimeout
. Но ваш первый комментарий несколько надуманный и не раскрывает законного варианта использования, а просто показывает, как он может сломаться. Я просто говорю, что вы не должны использовать a,=>
если вам это не нужно по уважительной причине, особенно в методах экземпляра класса, где это приводит к снижению производительности при создании новой функции, связанной с созданием экземпляра.просто пример того, как выстоять жирную стрелу
не работает: (@canvas undefined)
работает: (@canvas определен)
источник