При создании классов в coffeescript, есть ли причина не использовать жирную стрелку для методов экземпляра?

При построении классов в coffeescript, всегда ли есть причинане использовать жирную стрелку, например, методы?

Редактировать: Хорошо, тогда! Отличный ответ! :)

Подводя итог, проблемы:

- занимает больше памяти

- невозможность патча

- Напрашивается вопрос, почему он используется для этого метода?

Конвенция:

- Будьте явными при связывании функций.

- Объявлять жирные стрелочные методы в конструкторе.

- Используйте столько, сколько хотите, только не в объявлениях классов.

 owensmartin23 июн. 2014 г., 04:02
Это должно быть наиболее подходящее использование, яслышал "напрашивается вопрос " и его соответствующая ошибка в компьютерном программировании!
 Simon Landeholm03 дек. 2012 г., 13:21
Так что'Просто вопрос производительности?
 Thilo03 дек. 2012 г., 13:13
может быть полезно:stackoverflow.com/questions/8965855/...
 Thilo03 дек. 2012 г., 13:13
не использовать жирную стрелку, когда вы неТебе не нужно, это легче. Не уверен, если это имеет большое значение, хотя.
 davidpfahler03 дек. 2012 г., 14:45
Да. Также это позволяет избежать непредвиденных последствий. Вы всегда должны знать, почему вы добавляете что-то к поведению по умолчанию. Позже в вашем проекте вы не будете помнить, что все связано с помощью жирной стрелки, и вы будете преследовать ошибки, которые иначе никогда бы не произошли.
 robkuz03 дек. 2012 г., 15:34
также иногда может быть полезно использовать экземпляр в качестве объекта замыкания и передать метод в качестве обратного вызова другому методу.

Ответы на вопрос(2)

Решение Вопроса

есть причины не использовать жирные стрелки всегда. На самом деле ябуду утверждать в пользуникогда используя жирные методы :)

Методы тонких стрелок и толстых стрелок - концептуально разные вещи. Первые компилируются в ожидаемый JS-код на основе прототипа; методы принадлежат прототипу класса. Методы, обозначенные жирными стрелками, с другой стороны, связаны с каждым экземпляром в конструкторес кодом.

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

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

class Foo
  # Using fat-arrow method
  bar: (x) => alert x

# I have some Foos
foos = (new Foo for i in [1..3])

# And i want to path the bar method to add some logging. 
# This might be in another module or file entirely.
oldbar = Foo::bar
Foo::bar = (args...) ->
  console.log "Foo::bar called with", args
  oldbar.apply @, args

# The console.log will never be called here because the bar method 
# has already been bound to each instance and was not modified by 
# the above's patch.
foo.bar(i) for foo, i in foos

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

Код становится более противоречивым, потому что перед введением методов жирной стрелки в любое время мы видим:  в определении класса мы знаем, что это значит "объявить свойство с именем со значением в классе' прототип" (Если не указано == 'constructor', что является частным случаем), это нене имеет значения, если это число или функция, это будет просто свойство в прототипе. С введением жирных стрелок у нас теперь есть еще один ненужный особый случай: если это функция с жирными стрелками, она будет делать совсем другое, чем с любым другим значением.

И там'Еще одно несоответствие: жирные стрелкисвязатьthis по-другому когда они используются в определении метода, чем когда-либо еще. Вместо сохранения внешнегоthis (который внутри,classthis связан с конструктором класса)this внутри метода с жирными стрелками находится объект, который не существует, когда метод определен (то есть экземпляр класса).

Если вы смешиваете методы с тонкими стрелками и жирными стрелками, то коду также становится сложнее следовать, потому что теперь каждый раз, когда разработчик видит метод с толстыми стрелками, он 'Спрошу себя, зачем это нужно былотот метод для привязки к экземпляру. Там'нет непосредственной связи между методомдекларация и где онаs, где возникает необходимость в методе жирной стрелки.

За все это яРекомендую никогда не использовать жирные стрелы. Предпочитаю привязывать метод к экземпляру, где онбудет использоваться вместо того, где метод объявлен. Например:

# Be explicit about 'onClick' being called on 'someObject':
$someJQueryElement.on 'click', (e) -> someObject.onClick e

# Instead of:
$someJQueryElement.on 'click', someObject.onClick

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

# Instead of fat-arrow methods:
class A
  constructor: ->
    @bar = 42
  foo: => 
    console.log @bar

# Assing the method in the constructor, just like you would 
# do with any other own property
class A
  constructor: ->
    @bar = 42
    @foo = => 
      console.log @bar

Я думаю, что во втором определенииclass A Это'гораздо яснее, что происходит сfoo метод, чем в первом определении.

Наконец, обратите внимание, что яя не спорю против использования жирной стрелки вообще. Это'очень полезная конструкция, и я все время использую ее для нормальных функций; я просто предпочитаю избегать его использования внутриclass определение метода :)

редактировать: Еще один случай против использования жирных стрелок: функции-декораторы:

# A decorator function to profile another function.
profiled = (fn) ->
  (args...) ->
    console.profile()
    fn.apply @, args
    console.profileEnd()

class A
  bar: 10

  # This works as expected
  foo: profiled (baz) ->
    console.log "@bar + baz:", @bar + baz

  # This doesn't
  fatArrowedFoo: profiled (baz) =>
    console.log "@bar + baz:", @bar + baz

(new A).foo 5           # -> @bar + baz: 15
(new A).fatArrowedFoo 5 # -> @bar + baz: NaN
 Simon Landeholm04 дек. 2012 г., 16:17
Хорошо, нене ожидал такого сложного ответа! Буду читать позже ...
 programstinator17 сент. 2014 г., 14:55
@epidemian отличный ответ! Есть ли способ получить доступ к свойствам класса изнутри жирных стрелочных функций? я вижу это@bar не определено в вашемfatArrowedFoo функция. Я предполагаю, что я'я спрашиваю, как можно съесть мой торт и съесть его тоже :)
 epidemian17 сент. 2014 г., 15:32
@ Goran_Mandic, вы можете использовать декораторы для методов, если высвязать их на конструкторе, Внутри конструктораthis будетA например, неA сам. Но в рамках определения класса,this являетсяAи у Coffee нет возможности узнать, что жирная стрелка функционирует в некотором произвольном выражении (т.е.profiled (baz) -> ...) на самом деле предназначен для привязки кA экземпляры вместоA сам. Надеюсь, это имеет смысл: P
 epidemian06 дек. 2012 г., 14:30
@SimonLandeholm, я вижу в них разные проблемы. В случае с декоратором жирная стрелка неделать то, что ожидается: вместо привязкиthis с созданным экземпляром, он связывает его с конструктором класса (то же самое происходит, если вы простодобавить скобки вокруг функции жирной стрелки). Невозможность исправления является следствием нарушения предположения о том, чтоthis метода лениво связан (например,[].slice.call(arguments) является обычной конструкцией JS, которая опирается на это предположение)
 Simon Landeholm06 дек. 2012 г., 12:18
Что касается декоратора проблема неНеужели это та же самая проблема, что и невозможность исправления?
 programstinator17 сент. 2014 г., 16:29
Это действительно, на самом деле .. Теперь я понимаю, что ваш ответ содержал ответ и на мой вопрос, все это время. Я предполагаю, что это было только немного много, чтобы переварить сразу. Большое спасибо!
 yangmillstheory22 дек. 2014 г., 00:15
Upvoted за указание на то, что он полностью нарушает наследование прототипа и создает копию метода для каждого экземпляра. Одно это удивительное поведение, чтобы избежать использования жирных стрелок.
 yangmillstheory22 дек. 2014 г., 00:21
Единственным преимуществом использования жирных стрелочных методов является постоянное связывание, позволяющее избежать беспокойства о несвязанных методах, используемых в качестве обратных вызовов, что вы научитесь избегать в самом начале в JavaScript с помощью анонимных вызовов или.Function.prototype.bind

Сложные причины, высказанные @epidemian для избежания жирной стрелки, хороши и хороши, но учтите следующее:

если ты нене волнует (много или вообще) о "базовый JS-код на основе прототипа " сгенерированный CoffeeScript, поскольку вы можете писать последовательный и безошибочный код CoffeeScript;если ты нене планирую написать крошечный класс аля Java, который будет тратить 99% своего времени на вызовы друг друга »s методы вверх и вниз по дереву наследования и выполнение небольшой работы в процессе; сказал по-другому, если вы признаете, что чувствительны к производительностивнутренние петли " не очень хорошее место для вызова методов;если ты нене планируют украшать, исправлять обезьяны или иным образом модифицировать ваши классы методы во время выполнения;если вы указали использование жирной стрелки в комментарии к заголовку, для будущих разработчиков, работающих над вашим кодом;

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

Это сделает ваш код CoffeeScript более простым, безопасным и интуитивно понятным, потому что вы будете знать, чтоthis а также@ всегда обращайтесь к текущему объекту, метод которого вы определяетеКак и в большинстве других языков программирования, независимо от того, кто будет вызывать ваши функции и методы во время выполнения.

Говоря более формально, жирная стрела делаетthis ключевое слово (и его сокращение@) полностью лексически ограничен, как и любой другой идентификатор. История языка программирования показывает, что лексическая область видимости является наиболее интуитивным и менее подверженным ошибкам способом определения идентификаторов области. Тот'Почему это стало стандартным поведением для всех новых языков давно.

Если вы выберете этот путь,тонкая стрела становится исключениеми полезный в этом. Вы будете использовать его для подготовки тех конкретных обратных вызовов, где вам нужноthis ссылаться на что-то определенное во время выполнения вызывающей стороной, а не вашим собственным объектом. Это нелогичное значениеthis, но некоторым библиотекам JS необходимо такое поведение в пользовательских функциях. Тонкая стрелка будет служить для выделения этих фрагментов кода. Если я правильно помню, jQuery обычно предоставляет все, что вам нужно в аргументах функции, поэтому вы можете игнорировать ее искусственноеthis, но другие библиотеки не так доброжелательны.

NB. В CoffeeScript 1.6.1 есть ошибка, связанная с методами жирных стрелок, поэтому вам следует избегать этого. Предыдущие и более поздние версии должны быть в порядке.

Спектакль

При использовании в качестве обычной (анонимной) функции жирная стрелка не добавляет никаких накладных расходов. В объявлениях методаэто добавляеткрошечный ОЗУ и загрузка ЦП (действительно крошечный: несколько наносекунд и несколько байтов оперативной памяти для каждого вызова метода, и последний исчезает в механизмах с оптимизацией хвостового вызова.)

ИМХО ясность языка и безопасность жирной стрелки дают взамен достаточное основание терпеть и даже приветствовать небольшие накладные расходы. Многие другие идиомы CoffeeScript добавляют свои крошечные накладные расходы к сгенерированному коду (для циклов и т. Д.) С целью сделать поведение языка более согласованным и менее подверженным ошибкам. Жирная стрела ничем не отличается.

 Tobia24 июн. 2014 г., 00:36
@owensmartin you 'Добро пожаловать Фактически, я обычно определяю свои обратные вызовы как методы жирной стрелки с описательным именем, чтобы я мог передать их в библиотеки в качестве значений:someLibrary.doSomething 1, 2, @somethingWasDone Это превращает мой код в линейную последовательность вызовов методов, без вложенных пирамид-> и связанные с этим переменные вопросы объема.
 owensmartin23 июн. 2014 г., 20:25
Спасибо за этот ответ. Я'Я на самом деле делает именно это в веб-приложении, яЯ пишу. В частности, Express ожидает функцию, которая принимает(req, res, next) в качестве параметров, а затемВы можете удерживать эти объекты во время обработки. Учитывая, что большая часть того, что я хочу сделать, связана с вводом-выводом, либо в БД, либо в Интернет, я теряюсь во многих вложенных обратных вызовах. Это способ связатьreq а такжеres на любой обратный звонок мне нужно; Это'Это супер полезно.
 Rostyslav Diachok07 окт. 2014 г., 16:29
Даже создатель javascript говорит, что использование наследования прототипов не является хорошей идеей на сегодняшний день.youtube.com/watch?v=bo36MrBfTk4#t=1896
 robkuz08 июл. 2013 г., 21:37
хм, я не уверен, если бы я действительно рекомендовал ваш подход - внешне это кажется правильным - абсолютно так. Однако я думаю, что указанное вами предварительное условие, касающееся исправления обезьян и т. Д., Является недостижимым в реальности, что вызовет проблемы. Помимо этого - очень интересный подход. Может быть, было бы любезно, если бы вы проголосовали за мой вопрос и ответ, если уже ссылались на него ;-)
 Tobia08 июл. 2013 г., 23:04
Я считаю, что это будет сильно зависеть от типа проекта. В средне-крупномасштабном проекте (от 10 тыс. До мс строк кода) или в проекте, который стремится стать таковым, наличие такой согласованности - хорошая вещь. Зная, что каждый@ кем бы нис классом всегда значит "атрибут текущего экземпляра определяемого класса " бесценен. Неудивительно, что в таких проектах обычно не одобряют исправления обезьян и другие динамические изменения кода по той же причине: это усложняет (замедляет) понимание кода, который вы не делали.т, так что, в конце концов, это стоит дороже. (проголосовал, извините за это)
 yangmillstheory22 дек. 2014 г., 00:19
Пункты с пулей по существу отстаивают использование жирных стрелок, если вы: (1) нене заботится о скомпилированном JS, (2)не планирую создавать приложение вокруг "газиллион " разные предметы (читай "в развязанном виде), (3) нене взломав ссылку на прототип, (4) способны документировать то, что вымы сделали. Да я неНе думаю, что этот подход для меня.

Ваш ответ на вопрос