Возможно, я не правильно понял вопрос, потому что не понимаю, почему вы не добавляете код для вызова обратных вызовов непосредственно в коде myplugin:
$.fn.myplugin = function(method)
{
if (mp[method])
{
var params = Array.prototype.slice.call(arguments, 1), ret;
// you might want the callbacks to receive all the parameters
mp['doCallbacks'].apply(this, method + '_before', params);
ret = mp[method].apply(this, params);
mp['doCallbacks'].apply(this, method + '_after', params);
return ret;
}
// ...
}
РЕДАКТИРОВАТЬ:
Хорошо, после прочтения вашего комментария я думаю, что другим решением будет (конечно) другое косвенное.То есть иметь функцию invoke, которая используется из конструктора, а также другие открытые методы для вызовов между собой.Я хотел бы отметить, что он будет работать только для открытых методов, так как присоединение к хукам приватных методов в любом случае нарушает инкапсуляцию.
Простая версия будет выглядеть примерно так:
function invoke(method) {
var params = Array.prototype.slice.call(arguments, 1), ret;
// you might want the callbacks to receive all the parameters
mp['doCallbacks'].apply(this, method + '_before', params);
ret = mp[method].apply(this, params);
mp['doCallbacks'].apply(this, method + '_after', params);
}
$.fn.myplugin = function() {
// ...
invoke('init');
// ...
};
Но на самом деле я написал немного больше кода, который также уменьшил бы дублирование между плагинами.Вот как будет выглядеть создание плагина в конце
(function() {
function getResource() {
return {lang: "JS"};
}
var mp = NS.plugin.interface({
foo: function() {
getResource(); // calls "private" method
},
bar: function() {
this.invoke('foo'); // calls "fellow" method
},
init: function() {
// construct
}
});
$.fn.myplugin = NS.plugin.create(mp);
})();
А вот так выглядит частичная реализация:
NS = {};
NS.plugin = {};
NS.plugin.create = function(ctx) {
return function(method) {
if (typeof method == "string") {
arguments = Array.prototype.slice.call(arguments, 1);
} else {
method = 'init'; // also gives hooks for init
}
return ctx.invoke.apply(ctx, method, arguments);
};
};
// interface is a reserved keyword in strict, but it's descriptive for the use case
NS.plugin.interface = function(o) {
return merge({
invoke: NS.plugin.invoke,
callbacks: {},
addCallback: function(hook_name, fn, priority) {},
doCallbacks: function() {}
}, o);
};
NS.plugin.invoke = function(method_name) {
if (method_name == 'invoke') {
return;
}
// bonus (if this helps you somehow)
if (! this[method]) {
if (! this['method_missing') {
throw "Method " + method + " does not exist.";
} else {
method = 'method_missing';
}
}
arguments = Array.prototype.slice.call(arguments, 1);
if (method_name in ["addCallbacks", "doCallbacks"]) {
return this[method_name].apply(this, arguments);
}
this.doCallbacks.apply(this, method_name + '_before', arguments);
var ret = this[method_name].apply(this, arguments);
this.doCallbacks.apply(this, method_name + '_after', arguments);
return ret;
};
Конечно, это полностью не проверено:)