After studying several ways of doing OOP in JavaScript I think I finally came up with one that seems OK to me. Is it okay? Do you see some problems I can face by using OOP in JavaScript like this?
var Operators = (function ($, self) {
var self = {};
//private
var IPT_X = '#x';
var IPT_Y = '#y';
//public
self.x = 0;
self.y = 0;
//public
self.showOperators = function() {
//use of a private property (IPT_X) and a public property (this.x)
$(IPT_X).val(self.x);
$(IPT_Y).val(self.y);
};
self.clean = function() {
self.x = 0;
self.y = 0;
// call to a local public method
self.showOperators();
};
self.updateOperators = function(_x, _y) {
// use of a public property
self.x = _x;
self.y = _y;
};
self.clean();
return self;
//Module dependencies
})(jQuery, {});
var Randomizer = (function(self, math) {
// private
function getRandomNumber() {
return math.round(math.random() * 1000);
};
// keep superior method so we can call it after overriding
self.oldUpdateOperators = self.updateOperators
// public
self.updateOperators = function(_x, _y) {
// call to superior class's method
self.oldUpdateOperators(_x, _y);
// call to method of superior object
self.showOperators();
};
self.populateRandomNumbers = function() {
// call to public local method (this.updateOperators())
// and to a local private method (getRandomNumber()))
self.updateOperators(getRandomNumber(), getRandomNumber());
};
// init
self.populateRandomNumbers();
return self;
})(Operators, Math)
var Operations = (function(self, $) {
//private
var IPT_RES = '#res';
var BTN_SUM = '#sum';
var BTN_SUBTRACT = '#subt';
var BTN_MULTIPLY = '#mult';
var BTN_DIVISION = '#div';
var BTN_CLEAN = '#clean';
var BTN_RAND = '#rand';
// private
function calcSum() {
return self.x + self.y;
};
function calcSubtraction() {
return self.x - self.y;
};
function calcMultiplication() {
return self.x * self.y;
};
function calcDivision() {
return self.x / self.y;
};
function showRes(val) {
$(IPT_RES).val(val);
};
//public
self.sum = function() {
// call to 2 local private methods
showRes(calcSum());
};
self.subtract = function() {
showRes(calcSubtraction());
};
self.multiply = function() {
showRes(calcMultiplication());
};
self.division = function() {
showRes(calcDivision());
};
// init
$(BTN_SUM).on('click', function() { self.sum() });
$(BTN_SUBTRACT).on('click', function() { self.subtract() });
$(BTN_MULTIPLY).on('click', function() { self.multiply() });
$(BTN_DIVISION).on('click', function() { self.division() });
$(BTN_CLEAN).on('click', function() { self.clean() });
$(BTN_RAND).on('click', function() { self.populateRandomNumbers() });
return self;
})(Randomizer, jQuery);
<html>
<body>
X: <input id='x'>
<br>
Y: <input id='y'>
<br>
Res: <input id='res'>
<br>
<input id='sum' type='button' value='+'>
<input id='subt' type='button' value='-'>
<input id='mult' type='button' value='*'>
<input id='div' type='button' value='/'>
<input id='clean' type='button' value='C'>
<input id='rand' type='button' value='Rand'>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
</body>
</html>
Pros:
- Clean code. Not much boilerplate code
- No need to use
.call
or.bind
which in my view make code harder to understand - Clearly defined inheritance
- No need to instantiate anything (new). The simple presence of the Class definition is enough for everything to work.
- Most OOP concepts available
- Clear separation on view and business layers once I don't need to define anything in html. All actions are bind in JavaScript
- Don't need to worry about prototypes
- I'm already using this approach in a production system and it's working okay.
Cons:
- I can't do a call to a higher method version. I mean, call to a "grandfather" class's method that has already been overridden. Only to the last method version. I rarely do this, so I think it's okay.
- Too different from what's normally done in JavaScript. Although, I'm really not sure about this one.
The objective of this question isn't a code review of a simple calculator. I'm a senior developer and studying JS for some time now and I develop in several other languages and FWs. You can take a look on other (more verbose) OOP methods I studied before in my blog's post here.
I'm perfectly aware how an MVC works and what should be the function for each layer. I have done a simple calculator as an example to show how I intend to do JS OOP. I have mixed UI handling code and logic on purpose just to simplify the example. In a real system I would have separated it in different classes. That goes to the names also. In actual code I always use VERY verbose names.
I tried to simplify OO in JS and created this technique. As I said it's already been used in a production system.
This question's intention is present this OOP format to other developers to see if it has any problems I'm not seeing. So I'm not worried with this specific task as it's a mere example. In order to focus answers to this point, please stick to ways of doing this in OOP.
If someone thinks it's ok I also would like to hear from you.
Edit
I created a new question with many of the recommended modifications, here: Simple object-oriented calculator - follow-up