Я знаю, что почти три года опаздываю на вечеринку, но, надеюсь, будущие читатели этого вопроса могут получить пользу от моего ответа. Ответ GSto выглядит великолепно с точки зрения разработки плагина jQuery, но имеет одну небольшую проблему: вызов mynamespace()
приводит к тому, что возвращаемый экземпляр jQuery затуманивается новыми методами. Вот пример этой проблемы:
$myDiv = $('.mydiv');
$myDiv.mynamespace().height(); // this will be `height' from mynamespace
$myDiv.height(); // this will STILL be `height' from mynamespace
// because it has overwritten $myDiv.height
Выбранный ответ не имеет этой проблемы, потому что amtec()
не является экземпляром jQuery, а является объектом, который вызывает свои методы с экземпляром jQuery в качестве контекста. Я взял концепции из обоих ответов и написал плагин пространства имен ниже:
(function($) {
$.namespace = function(namespaceName, closures) {
if ($.fn[namespaceName] === undefined) {
$.fn[namespaceName] = function executor(context) {
if (this instanceof executor) {
this.__context__ = context;
}
else {
return new executor(this);
}
};
}
$.each(closures, function(closureName, closure) {
$.fn[namespaceName].prototype[closureName] = function() {
return closure.apply(this.__context__, arguments);
};
});
};
})(jQuery);
Пример использования:
$.namespace('milosz', {
redify: function() {
$(this).css('color', '#ff0000');
},
greenify: function() {
$(this).css('color', '#00ff00');
}
});
$.namespace('milosz', {
blueify: function() {
$(this).css('color', '#0000ff');
}
});
$('.mydiv').milosz().redify(); // The HTML elements with class `mydiv' are now red
В коде используются некоторые довольно низкоуровневые подробности JavaScript, которые хорошо объяснены Расширенным руководством Джона Резига по JavaScript , но в общих чертах то, что происходит в примере, таково:
Когда вызывается milosz
(внутренне $.fn[namespaceName]
), this
указывает на экземпляр jQuery
, возвращаемый $('.mydiv')
. Следовательно, оператор if
переходит к блоку else
, и вызывается версия конструктора milosz
(именуемая внутри executor
по причинам, которые скоро станут очевидными). В конструктор передается единственный параметр: this
, указатель на jQuery
экземпляр, который будет контекстом выполнения для всех членов пространства имен milosz
. Мы входим обратно в оператор if
, на этот раз выполняя первый блок, в котором переданный экземпляр jQuery
сохраняется в переменной-члене с именем __context__
(которая, вероятно, имеет низкий шанс перезаписи). Созданный объект возвращается со ссылкой на исходный экземпляр jQuery
и любые обертки, добавленные к его прототипу с помощью вызовов $.namespace
. Эти оболочки просто выполняют методы, переданные в пространство имен milosz
с исходным объектом jQuery
в качестве контекста, как это происходит при выполнении redify
.
Бах, я знаю, что это глоток, в любом случае дело в том, что он работает как принятый ответ, но выглядит как ответ jQueryish, который для меня является лучшим из обоих миров.