I have been working on the user interface of my website (www.swalif.com: do use chrome to translate if you like to). Not being familiar with jQuery I started off with JavaScript and now the file is huge: about 1000 lines of code. Furthermore the code is getting complex to handle and change.
Therefore I was looking for a way I could approach this problem in an object oriented manner that would result in a clean, re-usable system with a good architecture. Also would be nice to use features as provided by JQuery to keep the code small.
The problem is that there are a lot of tools out there and I cannot decide which one to invest time into to accomplish this task. e.g. mootools, prototype, jQuery, etc. So I need someone to lead me in the right direction.
This is our website www.swalif.com. Any other suggestion are also welcome.
For object-oriented javascript development I would recommend John Resig's Simple javascript Inheritance. It is a tiny bit of javascript that allows you to define classes, derive from base classes and override methods.
var Person = Class.extend({
init: function(isDancing){
this.dancing = isDancing;
},
dance: function(){
return this.dancing;
}
});
var Ninja = Person.extend({
init: function(){
this._super( false );
},
dance: function(){
// Call the inherited version of dance()
return this._super();
},
swingSword: function(){
return true;
}
});
var p = new Person(true);
p.dance(); // => true
var n = new Ninja();
n.dance(); // => false
n.swingSword(); // => true
// Should all be true
p instanceof Person && p instanceof Class &&
n instanceof Ninja && n instanceof Person && n instanceof Class
I think you'd be better off with a framework that actively developed and is build with OOP with extendability, reusability, mixings, mutators in mind.
This is exactly why MooTools was created.
That said, if you're not familiar with JS, it would be pretty difficult to grasp MooTools, since it's not a framework for beginners. Then again, if you grasp the notion of OOP, you should be ok.
Don't actually use a framework to implement your OOP. You get a much richer understanding of Javascript as a language when you deal with the nitty gritty of using Javascript's very flexible function prototype system to implement OOP-like operations.
Read about it here: http://phrogz.net/JS/Classes/OOPinJS.html.
If you only need to organize your code and don't need libraries you may use http://code.google.com/p/joose-js/. Otherwise use the oop model of the library you are using.
Simple example
Module("Test", function (m) {
Class("Point", {
has: {
x: {
is: "rw",
init: 0
},
y: {
is: "rw",
init: 0
}
},
methods: {
clear: function () {
this.setX(0);
this.setY(0);
}
}
})
})
Related
I work with some advanced JavaScript people and they have used the SUPER keyword in their code. I admit, I don't have a good grasp of how and why one can and would use this.
Can someone direct me or show me how to become well versed in its usage and reasoning thereof?
Here are some examples:
openup: function( $super ) {
$super();
this.shop.enable_access();
}
addLeft: function( data ) {
var cell = Element('td');
if ( data.item_data ) {
var item = new SRIL(data.item_data);
item.attach(cell);
item.show();
}
return cell;
}
var SRIL = Class.create(Module, {
initialize: function( $super, data ) {
$super({ dom: 'show_line' });
this.data = data;
if ( data.Type[0] == 'Car' ) {
//some code
}
else {
// some code
}
}
});
JavaScript does not have such a thing.
Update: You should have a look at the documentation of the library that is in use here. This is a library feature, not a language one.
Since Javascript doesn't have classical inheritance, structured instead according to a prototypal/functional model, developers have made various attempts at re-creating the classical model. super is part of one such strategy. The particular problem it solves is in the case of a child object that has the same method – even if it's just the constructor – as the parent object. Without creating super as an alias to the parent's methods, accessing such methods becomes somewhat cumbersome (and, in some cases, impossible).
John Resig has a wrapper that shows this off fairly well. Note his use of _super() in the first example to call the parent object's dance method.
Introductory reading:
Prototypes as "classes"
OO JS
Following the patterns described above I create libraries/APIs as the following
var Proto = {
constructor: function () {
this.works = true;
},
method: function () {
return this.works;
}
};
Now for library users to interact with my prototypes (which do not supply factory functions) they have to instantiate and initialize the object
// instantiate
var p = Object.create(Proto);
// initialize
p.constructor();
This is an unfriendly and verbose way of forcing users to instantiate and initialize my objects.
personally since I use pd in all my applications I have the following sugar
// instantiate or initialize
var p = Proto.new();
// or without bolting onto Object.prototype
var p = pd.new(Proto);
However I think it's unkind to force pd onto users so I'm not sure what's the best way to make my libraries usable.
People create new instances of Proto and call .constructor themself
Force people to use pd
Give .create style factory functions
Give up and use new <Function> and .prototype
1 and 2 have already been mentioned.
3 would basically be
Proto.create = pd.new.bind(pd, Proto);
4 would make me sad but confirming to a known standard way of doing things increases usability.
Generally when using non-standard OO patterns what are the easiest mechanisms to allow people to use my library in their application?
I'm currently tempted to say
// here is my Prototype
Proto;
// here is how you instantiate a new instance
var p = Object.create(Proto);
// here is how you initialize it
// yes instantiation and initialization are seperate and should be.
p.constructor();
// Want sugar, use pd.new
For now, you probably make it easiest on your library clients if you use a small API that helps you with building a traditional constructor function, using syntax that looks almost like prototypes-as-classes. Example API usage:
// Superclass
var Person = Class.extend({
constructor: function (name) {
this.name = name;
},
describe: function() {
return "Person called "+this.name;
}
});
// Subclass
var Worker = Person.extend({
constructor: function (name, title) {
Worker.super.constructor.call(this, name);
this.title = title;
},
describe: function () {
return Worker.super.describe.call(this)+" ("+this.title+")";
}
});
var jane = new Worker("Jane", "CTO");
Implementations:
Simple JavaScript Inheritance
I’ve reimplemented Resig’s API, in a way that is possibly easier to understand: rauschma/class-js
I think the way to go is providing the new(Prototype, [arguments]) function as per the "use pd" option. It should even not be that bad from a dependency point of view (since you could have packaged this function separately anyway and is has just a couple of lines of code)
Offering a special function also fits in a sort of historic perspective. If you go way back to Smalltalk or even in more recent cases like Python you have separate functions for object creation (new) and initialization (init, the constructor) and the only only reason we don't notice the separation is because they provide syntactic sugar for object instantiation.
We have a set of classes created that depend on Prototype's Class implementation (and some Object.extend).
The problem is prototype is creating trouble when integrating with the rest of our applications (even with "noconflict" adapters and the such).
Does anybody know of a compatible Class implementation that does not mess with the global scope? Or has anybody been able to "extract" Prototype's to use it alone?
I wrote one a couple of years back (I should go revisit it, and give it a proper name) because I didn't like Prototype's handling of calling methods on the "superclass", which involves creating a function every time an overridden method is called (yes, really). It's very similar to Prototype's except for how you make supercalls; you can readily drop it in and search for super in your code and change it up. My implementation also makes it a bit easier to use named functions rather than anonymous ones, which is useful for many reasons, not least because it helps your tools help you. It also makes private "class" methods trivial. Details below.
But you don't have to use mine. There are other options that will require slightly more work to migrate your code to, but probably not a lot more:
John Resig's simple inheritance
Dean Edwards' mechanism
My issue with both of them is that they use function decompilation (so does Prototype's Class stuff), and function decompilation (e.g., calling toString on a function) has never been standardized and does not work on some mobile browsers. Resig's mechanism continues to work if function decompilation doesn't work, but it adds overhead to every method in that case (rather than only ones that make supercalls). My mechanism doesn't use function decompilation at all, adds no overhead to method calls, and even makes supercalls highly-efficient.
If you use my mechanism and your Prototype code looks like this:
var SuperThingy = Class.create({
foo: function(arg) {
console.log("SuperThingy: " + arg);
this._pseudoPrivate();
},
_pseudoPrivate: function() {
console.log("I'm not really private.");
}
});
var Thingy = Class.create(SuperThingy, {
foo: function(super, arg) {
console.log("Thingy: " + arg);
super(arg);
}
});
You can make minimal changes:
var SuperThingy = Helper.makeClass({
foo: function(arg) {
console.log("SuperThingy: " + arg);
this._pseudoPrivate();
},
_pseudoPrivate: function() {
console.log("I'm not really private.");
}
});
var Thingy = Helper.makeClass(SuperThingy, {
foo: function(arg) {
console.log("Thingy: " + arg);
this.callSuper(arguments, arg);
}
});
...or you can make slightly larger changes and get the benefit of a speed increase (callSuper uses arguments.callee, which is slow), properly-named functions (for debugging and such), and truly private functions:
var SuperThingy = Helper.makeClass(function() {
function SuperThingy_foo(arg) {
console.log("SuperThingy: " + arg);
trulyPrivate.call(this);
}
function trulyPrivate() {
console.log("I'm truly private.");
}
return {foo: SuperThingy_foo};
});
var Thingy = Helper.makeClass(SuperThingy, function() {
function Thingy_foo(arg) {
console.log("Thingy: " + arg);
foo.$super.call(this, arg);
}
return {foo: Thingy_foo};
});
The Prototype source tries to be modular so you can download lang/class.js separately. However a quick glance at the code shows it depends on functions from lang/array.js, lang/object.js, lang/function.js - it would be safer to grab prototype.js and all of the lang directory. That gives you the core of Prototype without the conflicting DOM stuff.
I too find the Class class too useful to do without. I was recommended to try Sugar which is nice but still has no inheritence. It seems the only real alternative currently is MooTools' class.
You should have a look at :
MyJS class system
I think you will enjoy !
After trying out ComposeJS, I couldn't find a way to invoke superclass constructors explicitly (they are invoked automatically), so I had to abandon it. I finally settled on JsFace which has many features (inheritance, mixins, static properties, AOP), although a slightly weird syntax to invoke the super class constructor: this.$class.$super.call(args). It also seems to be the fastest implementation, according to its website and also this benchmark, totally blowing away the Resig implementation, which is quite slow. The caveat to watch out for is is that this.$class.$super is always the super class of the final child class, so you may need to do something like this:
var C = Class(A, {
constructor: function (x) {
C.$super.call(this, x);
},
...
}
instead of
var C = Class(A, {
constructor: function (x) {
this.$class.$super.call(this, x);
},
...
}
which is like the examples, if you have multiple levels of inheritance, otherwise you'll get an infinite recursion.
I'm interesting in improving my javascript code to be properly OOP.... currently I tend to do something like this:
jQuery(document).ready(function () {
Page.form = (function () {
return {
//generate a new PDF
generatePDF: function () {
},
//Update the list of PDFs available for download
updatePDFDownloads: function () {
},
/*
* Field specific functionality
*/
field: (function () {
return {
//show the edit prompt
edit: function (id, name) {
},
//refresh the value of a field with the latest from the database
refresh: function (id) {
}
};
}())
};
}());
});
In the end it's just mainly organized functions I suppose... what's a good resource where I can learn to program javascript in an OOP manner, or what suggestions would you have for improving my current style of programming?
It seems like I should do a sort of model prototype and have my form object inherit from that prototype.
(I'm using jQuery instead of $ because of conflicts with prototypeJS)
Your question is quite broad so I don't think a complete answer is possible here. But here are a few points.
Regarding the code you have shown. You're jumping a couple of redundant hoops.
Unless you're accessing the DOM in some way, there is no need to wrap your code in jQuery(document).ready()
There is no need to return an object from a self calling anonymous function unless you're closing over some private functions or data
The object you have created can be created more simply (a good thing) like this
var Page = {
form: {
//generate a new PDF
generatePDF: function () {
},
//Update the list of PDFs available for download
updatePDFDownloads: function () {
},
/*
* Field specific functionality
*/
field: {
//show the edit prompt
edit: function (id, name) {
},
//refresh the value of a field with the latest from the database
refresh: function (id) {
}
}
}
};
It's easier to read and less confusing, only do things that buy you something. see cargo cult programming
Here's an example using a self calling anonymous function to create private members
var Obj = (function() {
privateFunction( param ) {
// do something with param
}
var privateVar = 10;
return {
// publicMethod has access to privateFunction and privateVar
publicMethod: function() {
return privateFunction( privateVar );
}
}
})();
The structure you have used, object literals are very good, as you say, at grouping a set of functions (methods) and properties. This is a kind of namespace. It is also a way of creating a Singleton. You may also want to create many objects of the same Class.
JavaScript doesn't have classes like traditional OO languages (I'll get to that) but at the simplest level it's very easy to create a 'template' for creating objects of a particular type. These 'templates' are normal functions called constructors.
// a constructor
// it creates a drink with a particular thirst quenchingness
function Drink( quenchingness ) {
this.quenchingness = quenchingness;
}
// all drinks created with the Drink constructor get the chill method
// which works on their own particular quenchingness
Drink.prototype.chill = function() {
this.quenchingness *= 2; //twice as thirst quenching
}
var orange = new Drink( 10 );
var beer = new Drink( 125 );
var i_will_have = ( orange.quenchingness > beer.quenchingness )
? orange
: beer; //beer
var beer2 = new Drink( 125 );
beer2.chill();
var i_will_have = ( beer2.quenchingness > beer.quenchingness )
? beer2
: beer; //beer2 - it's been chilled!
There's a lot to know about constructors. You'll have to search around. There are lots of examples on SO.
Inheritance, the foundation of OO, is not that intuitive in js because it is prototypal. I won't go into that here because you will more than likely not use js's native prototypal inheritance paradigm directly.
This is because there are libraries that mimic classical inheritance very effectively, Prototype (inheritance) or mootools (Class) for example. There are others.
Many say that inheritance is overused in OO and that you should favour composition and this brings me to what I initially set out to recommend when I started this rambling answer.
Design patterns in JavaScript are as useful as in any OO language and you should familiarise yourself with them
I recommend you read Pro JavaScript Design Patterns.
There, that's it
Some good sources for Object-Oriented JavaScript and JavaScript in general...
Online Articles
How to "properly" create a custom object in JavaScript?
https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript
http://mckoss.com/jscript/object.htm
http://ejohn.org/blog/simple-javascript-inheritance/
JavaScript: How To Get Private, Privileged, Public And Static Members (Properties And Methods)
Books
JavaScript: The Good Parts - Douglas Crockford
Object-Oriented JavaScript - Stoyan Stefanov
I hope this helps.
Hristo
There isn't one correct way... Some people use a framework to define their object, I like to just extend prototype directly. Anyhow, I wanted to say that Oran Looney has some good posts on OO mechanics in JS:
http://oranlooney.com/classes-and-objects-javascript/
Its also worth looking at his other articles:
http://oranlooney.com/deep-copy-javascript/
http://oranlooney.com/functional-javascript/
The top 3 I suggest to read is
JavaScript and Object Oriented Programming (OOP)
Classical Inheritance in JavaScript
Prototypal Inheritance in JavaScript
Have a nice reading!
The code we are using follows this basic structure:
//Create and define Global NameSpace Object
( function(GlobalObject, $, undefined)
{
GlobalObject.Method = function()
{
///<summary></summary>
}
}) (GlobalObject = GlobalObject || {}, jQuery);
//New object for specific functionality
( function(Functionality.Events, $, undefined)
{
//Member Variables
var Variable; // (Used for) , (type)
// Initialize
GlobalObject.Functionality.Events.Init = function()
{
///<summary></summary>
}
// public method
this.PublicMethod = function(oParam)
{
///<summary></summary>
///<param type=""></param>
}
// protected method (typically define in global object, but can be made available from here)
GlobalObject.Functionality.ProtectedMethod = function()
{
///<summary></summary>
}
// internal method (typically define in global object, but can be made available from here)
GlobalObject.InternalMethod = function()
{
///<summary></summary>
}
// private method
var privateMethod = function()
{
///<summary></summary>
}
}) (GlobalObject.Funcitonality.Events = GlobalObject.Funcitonality.Events || {}, jQuery )
The strength to this is that it initializes the Global object automatically, allows you to maintain the intergrity of your code, and organizes each piece of functionality into a specific grouping by your definition. This structure is solid, presenting all of the basic syntactical things you would expect from OOP without the key words. Even setting up intelisense is possible with javascript, and then defining each peice and referencing them makes writing javascript cleaner and more manageable. Hope this layout helps!
I dont think it matters what language you use, good OOP is good OOP. I like to split up my concerns as much as possible by using an MVC architecture. Since JavaScript is very event based, I also use the observer design pattern mostly.
Heres a tutorial you can read about MVC using jQuery.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I've been developing jQuery plugins for quite some time now, and I like to think I know how to design one well by now. One issue keeps nagging me though, and that is how to deal with private functions in a powerful yet elegant manner.
My plugins generally look something like this:
(function($) {
$.fn.myplugin = function(...) {
...
// some shared functionality, for example:
this.css('background-color', 'green');
...
};
$.fn.mypluginAnotherPublicMethod = function(...) {
...
// some shared functionality, for example:
this.css('background-color', 'red');
...
};
}(jQuery));
Now my question is: how to neatly DRY up that shared functionality? An obvious solution would be to put it in a function within the plugin's namespace:
var fill = function($obj, color) {
$obj.css('background-color', color);
};
Although this solution is effective and nicely namespaced, I really dislike it. For one simple reason: I have to pass it the jQuery object. I.e. I have to call it like this: fill(this, 'red');, while I would like to call it like this: this.fill('red');
Of course we could achieve this result by simply putting fill into jQuery.fn. But that feels very uncomfortable. Imagine having ten plugins developed based on this approach and each plugin putting five of those 'private' functions into the jQuery function namespace. It ends up in a big mess. We could mitigate by prefixing each of these functions with the name of the plugin they belong to, but that doesn't really make it more attractive. These functions are supposed to be private to the plugin, so we do not want to expose them to the outside world at all (at least not directly).
So there's my question: does anyone of you have suggestions for how to get the best of both worlds. That is; plugin code being able to call 'private' plugin functions in a way similar to this.fill('red') (or this.myplugin.fill('red') or even this.myplugin().fill('red') etc.), while preventing jQuery function namespace pollution. And of course it should be light-weight, as these private functions might be called very frequently.
UPDATE: Thanks for your suggestions.
I especially like David's idea of defining an object type that holds the 'private' functions and wraps a jQuery object. The only problem with it is that it still disallows me from chaining 'private' and 'public' functions. Which was big reason to want a syntax like this.fill('red') to begin with.
I ended up with a solution which I consider not tremendously elegant, but appealing to the 'best of both worlds' cause:
$.fn.chain = function(func) {
return func.apply(this, Array.prototype.slice.call(arguments, 1));
};
Which allows for constructs like:
this.
find('.acertainclass').
chain(fill, 'red').
click(function() {
alert("I'm red");
});
I cross-posted my question in other places, which also collected some interesting responses:
http://forum.jquery.com/topic/jquery-plugin-design-pattern-common-practice-for-dealing-with-private-functions
http://groups.google.com/group/jquery-en/browse_thread/thread/fa8ccef21ccc589a
One thing first: if you would like to call something like this.fill('red'); where this is an instance of jQuery, you have to extend the jQuery prototype and make fill() "public". jQuery provides guidelines for extending it's prototype using so called "plugins" that can be added using $.fn.fill, which is the same as jQuery.prototype.fill.
In jQuery callbacks, this is often a reference to the HTML Element, and you can't add prototypes to those (yet). That is one of the reason why jQuery wraps elements and return jQuery instances that can be easily extended.
Using the (function(){})(); syntax, you can create and execute "private" javascript on the fly, and it all disappears when it's done. Using this technique, you can create your own jQuery-like syntax that wraps jQuery into your own private chainable object.
(function(){
var P = function(elem) {
return new Private(elem);
};
var Private = function(elem) {
this.elem = jQuery(elem);
}
Private.prototype = {
elem: null,
fill: function(col) {
this.elem.css('background',col);
return this;
},
color: function(col) {
this.elem.css('color', col);
return this;
}
}
$.fn.myplugin = function() {
P(this).fill('red');
};
$.fn.myotherplugin = function() {
P(this).fill('yellow').color('green');
};
})();
$('.foo').myplugin();
$('.bar').myotherplugin();
console.log(typeof P === 'undefined') // should print 'true'
This way, the P stands for your own toolbox of "private" functions. They won't be available anywhere else in the code or in the jQuery namespace unless you attach them somewhere. You can add as many methods as you like in the Private object, and as long as you return this, you can also chain them jQuery-style as I did in the example.
How about (within the plugin's scope):
var fill = function ()
{
(function (color)
{
this.css ('backgrorund-color', color);
//.. your stuff here ...
}).apply (this, arguments);
}
$.fn.myplugin = function ()
{
fill ('green');
}
That way, fill will retain the jQuery context you're in, and is still private to your plugin
Amended: the above is incorrect w.r.t. scoping, Try the following instead:
var fill = function (color)
{
if (!$this) return; // break if not within correct context
$this.css ('backgrorund-color', color);
//.. your stuff here ...
}
$.fn.myplugin = function ()
{
var $this = $(this); // local ref to current context
fill ('green');
}
You might want to take a look at how the jQuery UI Widget Factory is implemented.
The basic approach is like this:
(function($){
$.fn.myplugin = function(method)
{
if (mp[method]) // map $('foo').myplugin('bar', 'baz') to mp.bar('baz')
{
return mp[method].apply(this, Array.prototype.slice.call(arguments, 1));
}
else if (typeof method === 'object' || ! method)
{
return mp.init.apply(this, arguments); // if called without arguments, init
}
else
{
$.error('Method ' + method + ' does not exist on $.myplugin');
}
};
// private methods, internally accessible via this.foo, this.bar
var foo = function() { … };
var bar = function() { … };
var private = { // alternative approach to private methods, accessible via this.private.foo
foo : function() { … },
bar : function() { … }
}
var mp = { // public methods, externally accessible via $.myplugin('foo', 'bar')
init : function( options )
{
return this.each(function()
{
// do init stuff
}
},
foo : function() { … },
bar : function() { … }
};
})(jQuery);
Unfortunately, "private" methods (or any property for that matter) can never be called with a "this" prefix in javascript. Anything which is called like this.myFunc(myArgs) must be publicly available.
And "private" methods can only be called from within the scope in which they were defined.
Your original solution is the only one that will work. Yes, it's a pain having to pass in this, but there's no more verbosity than there would be if your impossible request was possible:
this.fill('green');
//or
fill(this,'green');
As you can see, they both take up exactly the same number of characters in your code.
Sorry to say, but you're stuck with this as a solution, unless you want to create a new namespace and make them not private - which is simply going to add to the amount of code you need to write, i.e. what you indirectly called "not directly exposed":
this.myplugin.fill('green');
...is more verbose, thus kind of defeats the purpose.
Javascript is not like other languages, there are no "private" members per-se, only members accessible within closures, which can sometimes be used in a similar way to private members, but is more of a "workaround", and not the "real-deal" private members you are looking for.
It can be difficult to come to terms with this (I often struggle), but don't try to mould javascript into what you understand from other languages, take it for what it is...