There are ways in Javascript to have private members - state and behavior | values and functions/methods - but I'm not seeing it done often. Some minimal discipline in following a few rules is good enough to mitigate the (worst) issues. No langue - no matter how strongly or inferred or even static ...typed and compiled compensates for ingnorance in the problem space... After acquiring a decent understanding what is going on and sorting the things out in the mind, a few formal rules consistently applied foster an equally decent implementation. These are a few rules I stick with... but as you know: Rules can only exist when Exceptions to the Rule(s) exist... ;-)...
CamelCase and camelCase notation for all things (except for constants).
Constants all UPPER_CASE and 'mimicking camelCasing' with UNDER_SCORES.
Class names (which in Javascript are constructor functions are always starting with an UpperCase.
Members - state or behavior - start with lowerCase, and - if you want to pay attention to public and private, prefix it them with single underscore (_).
Above code uses private members - state (_inquiries) and behavior (_getXyz() ) to show what is all accessible from the outside and what should not be used for various reasons (hide implementation, allow change under the hood),...
Since there is only a single name space - the global name space - available, keeping as little as possible globals is very helpful. Therefore, not even functions should freely float around: they belong to a function library, which is like a singleton, sometimes named xyzUtils or just utils. It is though a good thing to be somewhat specific what the utility library is about.
var Person = function(first,last,birthDate) { // constructor expects String, String, Date
this.first = first;
this.last = last;
this.birthDate = birthDate;
this._inquiries = { ageInYears: 0, inquiries: 0 };
}
Person.prototype.getFullName = function() {
return this.first + " " + this.last;
}
Person.prototype.getAgeInYears = function() {
this._updateInquiries("ageInYears");
return this._getAgeInYears();
}
Person.prototype.getNumberOfAgeInquiries = function() {
this._updateInquiries("inquiries");
return this._inquiries.ageInYears;
}
Person.prototype.getSumOfAllInquiries = function() {
this._updateInquiries("inquiries");
return this._getSumOfInquiries();
}
Person prototype.getYearlyAverageOfInquiries = function() {
return this.getSumOfAllInquiries() / this._getAgeInYears();
}
Person.prototype._updateInquiries = function(fact) {
this._inquiries[fact]++;
}
Person.prototype._getAgeInYears = function() {
return new Date().getFullYear() - this.birthDate().getFullYear();
}
Person.prototype._getSumOfInquiries = function() {
this._updateInquiries("inquiries");
var sum = 0;
for (var fact in this._inquiries) { sum += this._inquiries[fact]; }
return sum;
}
var personUtils =
{ utilityFnctA: function(person,someOtherThing,andAThirdThing) {
// do what it has to do
}
, utilityFnctB: function(person,someXThing,someYThing) {
// do what it has to do
}
};
Since JavaScript by nature has closures, various frameworks have popped-up to overcome name space issues in order to mix and match components from various - non-synchronized - providers. One very useful library is node.js' require("module(Path)Name") and requirejs' require(["modulePathName1","modulePathName2",...],function(module1,module2,...){ ... };. The first one is more server-side oriented, and latter more client - Browser - side oriented. Both keep a cache to load a thing only once. The second goes though farther in functionality: first is usually synchronous, where the second one is usually asynchronous and handles the load of all modules like a promise and enters the anonymous function only after all modules have been loaded. In a 'small' world like an mc, the first one works just good enough.
Espruino is a JavaScript interpreter for low-power Microcontrollers. This site is both a support community for Espruino and a place to share what you are working on.
There are ways in Javascript to have private members - state and behavior | values and functions/methods - but I'm not seeing it done often. Some minimal discipline in following a few rules is good enough to mitigate the (worst) issues. No langue - no matter how strongly or inferred or even static ...typed and compiled compensates for ingnorance in the problem space... After acquiring a decent understanding what is going on and sorting the things out in the mind, a few formal rules consistently applied foster an equally decent implementation. These are a few rules I stick with... but as you know: Rules can only exist when Exceptions to the Rule(s) exist... ;-)...
Since there is only a single name space - the global name space - available, keeping as little as possible globals is very helpful. Therefore, not even functions should freely float around: they belong to a function library, which is like a singleton, sometimes named xyzUtils or just utils. It is though a good thing to be somewhat specific what the utility library is about.
Since JavaScript by nature has closures, various frameworks have popped-up to overcome name space issues in order to mix and match components from various - non-synchronized - providers. One very useful library is node.js'
require("module(Path)Name")
and requirejs'require(["modulePathName1","modulePathName2",...],function(module1,module2,...){ ... };
. The first one is more server-side oriented, and latter more client - Browser - side oriented. Both keep a cache to load a thing only once. The second goes though farther in functionality: first is usually synchronous, where the second one is usually asynchronous and handles the load of all modules like a promise and enters the anonymous function only after all modules have been loaded. In a 'small' world like an mc, the first one works just good enough..