Как лучше понять Coffeescript/JavaScript mixins?
Я читал на Mixins, используя Coffeescript или просто Javascript из следующих источников:
http://arcturo.github.com/library/coffeescript/03_classes.html (внизу)
и
http://javascriptweblog.wordpress.com/2011/05/31/a-fresh-look-at-javascript-mixins/
И хотя я могу скомпилировать различные примеры, у меня есть главный вопрос, который, кажется, мешает мне добиться прогресса в их понимании.
Я понятия не имею, что происходит в мире. Чтобы начать, я объясню, что Коффисскрипт меня смущает.
moduleKeywords = ['extended', 'included']
class Module
@extend: (obj) ->
for key, value of obj when key not in moduleKeywords
@[key] = value
obj.extended?.apply(@)
this
@include: (obj) ->
for key, value of obj when key not in moduleKeywords
# Assign properties to the prototype
@::[key] = value
obj.included?.apply(@)
this
Здесь возникает ряд вопросов.
-
Прежде всего, что мы делаем с переменной moduleKeywords
? Я не понимаю, что это делает.
-
Во-вторых, как работает extended?.apply(@)
? Что здесь происходит? Я могу посмотреть компиляцию JavaScript и посмотреть следующий код.
Module.extend = function(obj) {
var key, value, _ref;
for (key in obj) {
value = obj[key];
if (__indexOf.call(moduleKeywords, key) < 0) {
this[key] = value;
}
}
if ((_ref = obj.extended) != null) {
_ref.apply(this);
}
return this;
};
Может ли кто-нибудь пролить некоторый общий свет на это?
С более глубоким нажатием The Little Book on Coffeescript
я вижу реализацию.
ORM =
find: (id) ->
create: (attrs) ->
extended: ->
@include
save: ->
class User extends Module
@extend ORM
Вот как я это прочитал:
- создать литерал
ORM
.
- Объявить метод
find
принятия параметра.
- Объявить метод "create", принимающий параметр.
- Объявить метод 'extended', с под-методом 'include', с под-методом 'save'.
Здесь я получаю самую большую потерю.
Литеральный ORM
имеет метод extended
, а затем Module
реализуется/расширяется классом User
. Поэтому я считаю, что User
имеет ту же форму, что и Module
. Эта часть имеет смысл до сих пор, упрощенное наследование. Но потом я теряюсь на @extend ORM
.
@extend
- это метод на Module
, но что делает метод extended
? Когда это называется? Как это реализовано?
Ответы
Ответ 1
-
extend
копирует методы из объекта "module" на расширяемый объект
-
include
копирует методы из объекта "module" на прототип расширяемого объекта
1 moduleKeywords
используется для защиты некоторых методов модуля, поэтому они не копируются в объект, потому что они имеют особое значение
2 extended?.apply(@)
говорит, что , если модуль имеет свойство с именем extended
, чем предполагать его функцией, а затем вызывает эту функцию с "this" в функции, равной @, @, являющейся расширенным объектом, вы можете думать об этом как о чем-то вроде (хотя и не совсем, но это просто интуиция) @.extended()
(@== this in coffeescript)
"применить" функцию в JS
экзистенциальный оператор в CS
Ответ 2
Вы путаетесь по смыслу и используете расширенные и включенные ключевые слова модуля. Но в книге объясняется, что они используются как обратные вызовы после расширения и включения.
Итак, в последнем примере ORM имеет "расширенный" обратный вызов. Функция "продлить" будет в конце вызова "расширена" и передать ее @(или это или в нашем примере User), так что включение @(this.) Также будет выполняться на пользователе, и оно будет включать функцию "сохранить".
Вы также можете сделать обратное:
ORM =
save ->
included: ->
@extend
find: (id) ->
create: (attrs) ->
class User extends Module
@include ORM