patternjavascriptMinor
Private methods and properties in jQuery "lightweight start" pattern
Viewed 0 times
propertieslightweightprivatemethodsjquerystartandpattern
Problem
For non-plugin code, I generally use the module pattern, but I'm working on a jQuery plugin and decided to try out the "lightweight start" pattern. The problem is, I find myself needing
Is there a better way to structure the code in order to avoid
Jsfiddle example without $.proxy ... also have a jsfiddle example using $.proxy
Edit:
What I learned. This pattern appears to actually make all methods private. This is because the
$.proxy when calling private methods to ensure the this context. Is there a better way to structure the code in order to avoid
$.proxy, while ensuring the private methods have access to the init() method's this context? Where exactly should I define private properties?Jsfiddle example without $.proxy ... also have a jsfiddle example using $.proxy
(function($, window, document, undefined) {
var pluginName = "myPlugin",
defaults = {
opt1: "#opt1",
};
function Plugin(element, options) {
this.element = $(element);
this.options = $.extend( {}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
Plugin.prototype.init = function() {
this.counter = 1;
$("div").each(privateMethod1);
$("body").on("click", this.options.opt1, event1);
};
function privateMethod2(i, div) {
// "this" context is Window, not Plugin
$(div).append(i);
this.element.append(this.counter);
};
function privateMethod1(i, el) {
// "this" context is Window, not Plugin
this.counter += 1; // undefined, but defined in init()
privateMethod2(i, el);
};
function event1(ev, el) {
this.counter += 1; // undefined, but defined in init()
privateMethod1(this.counter, el);
};
$.fn[pluginName] = function(options) {
return this.each(function() {
if (!$.data(this, "plugin_" + pluginName)) {
$.data(this, "plugin_" + pluginName, new Plugin(this, options));
}
});
};
}(jQuery));Edit:
What I learned. This pattern appears to actually make all methods private. This is because the
if (!$.data(this, "plugin_" + pluginName)) { has no else block to handle elements that already have a reference to the plugin. To allow a method to be called, check out https://stackoSolution
You could use a closure to create your own proxy.
Why are
Edit: Instead of using plain functions to implement "private methods", promote them to proper object methods and mark them private using JSDoc. This will save you those extra calls to
In my opinion, forcing developers to jump through hoops just to hide private methods is a net loss.
Plugin.prototype.init = function() {
var self = this;
rows.each(function (groupIndex, group) {
self.initGroup(groupIndex, group);
});
this.container.on("click", this.options.addBtnId, function (ev) {
self.addGroup(ev);
});
};Why are
initGroup and addGroup using $.proxy? They are already being called with the correct this context, and rebinding to the same context changes nothing.Edit: Instead of using plain functions to implement "private methods", promote them to proper object methods and mark them private using JSDoc. This will save you those extra calls to
$.proxy./** @private */
Plugin.prototype.initGroup = function(groupIndex, group) {
this.addFieldIds(groupIndex, group);
};
/** @private */
Plugin.prototype.addGroup = function(ev) {
this.initGroup(this.maxGroupIndex, newGroup);
};In my opinion, forcing developers to jump through hoops just to hide private methods is a net loss.
Code Snippets
Plugin.prototype.init = function() {
var self = this;
rows.each(function (groupIndex, group) {
self.initGroup(groupIndex, group);
});
this.container.on("click", this.options.addBtnId, function (ev) {
self.addGroup(ev);
});
};/** @private */
Plugin.prototype.initGroup = function(groupIndex, group) {
this.addFieldIds(groupIndex, group);
};
/** @private */
Plugin.prototype.addGroup = function(ev) {
this.initGroup(this.maxGroupIndex, newGroup);
};Context
StackExchange Code Review Q#45369, answer score: 4
Revisions (0)
No revisions yet.