This question is an improvement I did based on recommendations from these other questions:
Simple object-oriented calculator
Simple object-oriented calculator - follow-up
To those looking this question first I'm trying to find a correct OOP model I can use in JS. I initially found a very different solution from what's normally done and I received lots of help from some of the good guys here :) The links above tell the whole story.
And I guess I'm finally coming to grips with it. Please take a look.
function ViewBase() {
Object.defineProperty(this, "parse", {
value: function() {
for(prop in this)
this[_.camelCase(prop)] = $('#' + this[prop]);
},
writable: true,
enumerable: false
});
};
// View class mirroring html components
function ViewCalc () {
this.IPT_X = 'x';
this.IPT_Y = 'y';
this.IPT_RES = 'res';
this.BTN_SUM = 'sum';
this.BTN_SUBTRACT = 'subt';
this.BTN_MULTIPLY = 'mult';
this.BTN_DIVISION = 'div';
this.BTN_CLEAN = 'clean';
this.BTN_RAND = 'rand';
this.parse();
};
ViewCalc.prototype = new ViewBase();
function Operands() {
// connect view to the base business class
this.view = new ViewCalc();
//public
this.x = 0;
this.y = 0;
//public
this.showOperands = function() {
//use of a private property (IPT_yyX) and a public property (this.x)
this.view.iptX.val(this.x);
this.view.iptY.val(this.y);
};
this.clean = function() {
this.x = 0;
this.y = 0;
// call to a local public method
this.showOperands();
};
this.updateOperands = function(x, y) {
// use of a public property
this.x = x;
this.y = y;
};
this.clean();
};
function Randomizer() {
// private
function getRandomNumber() {
return Math.round(Math.random() * 1000);
};
this.updateOperands = function(x, y) {
// call to superior class's method
Randomizer.prototype.updateOperands.call(this, x, y);
// call to method of superior object
this.showOperands();
};
this.populateRandomNumbers = function() {
// call to public local method (this.updateOperands())
// and to a local private method (getRandomNumber()))
this.updateOperands(getRandomNumber(), getRandomNumber());
};
// init
this.populateRandomNumbers();
};
Randomizer.prototype = new Operands();
function Operations() {
//public
this.sum = function() {
// call to 2 local private methods
showRes(doSum());
};
this.subtract = function() {
showRes(doSubtraction());
};
this.multiply = function() {
showRes(doMultiplication());
};
this.division = function() {
showRes(doDivision());
};
var self = this;
// private
function doSum() {
return self.x + self.y;
};
function doSubtraction() {
return self.x - self.y;
};
function doMultiplication() {
return self.x * self.y;
};
function doDivision() {
return self.x / self.y;
};
function showRes(val) {
self.view.iptRes.val(val);
};
// init
this.view.btnSum.on('click', function() { self.sum() });
this.view.btnSubtract.on('click', function() { self.subtract() });
this.view.btnMultiply.on('click', function() { self.multiply() });
this.view.btnDivision.on('click', function() { self.division() });
this.view.btnClean.on('click', function() { self.clean() });
this.view.btnRand.on('click', function() { self.populateRandomNumbers() });
};
Operations.prototype = new Randomizer();
var o = new Operations();
<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://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
What I did this time:
from @tkellehe and @SirPython answers:
- I'm realizing that using this self variable is causing more harm than does good. So I reverted to this, new and prototype usage.
from @tkellehe answer:
- I remove all _vars from parameters, all private vars will use it from now on. Just there aren't any at the example at the moment.
- I used Object.define in View classes so I don't need to use Object.keys anymore.
- Because I reverted to this, new and prototype usage, override function doesn't work/it's not needed anymore. So I had to use Class.prototype.method.call instead and I don't need a Base class anymore or a salvage to not using new. At least at this point.
- I know loading within context is important and I'll use it. I just don't think it's needed for this example. But that library loading function was really cool. Thanks.
What still bothers me:
- I don't like using Class.prototype.method.call. It's too long... too clumsy. Is there a better solution for calling the superior method ? Can you make override function work again in this format ?
- In ViewCall and ViewBase classes it would be better if I could put this.parse() in ViewBase class in such a manner that it get called in the moment ViewClass was instatiated. But I couldn't find a way to do it. Someone has an idea how I could do this ?
Better ? comments ?