There is currently a conversation going in that respect - Serial.on() issues - which is actually more a about this, context classes, objects (instances of classes), functions, methods, callbacks, etc.
Javascript has a bit a quirky looking way of instantiating an object from a given class: issuing var inst1 = new MyFunction() makes MyFunction() a class definition - or constructor function - that defines - and constructs - (usally the state of) an object - hence the convention of starting Uppercase. Issuing it a second time var inst2 = new MyFunction() creates actually a second, different instance - but with the same properties - state (and behavior).
Invoking a capability, function, or behavior of that class of objects is then more suitably called invoking a method. Defining methods (behavior) is done by assigning functions to the prototype of the (state) defining function.
To make it more obvious, lets, call the "MyFunction" a "Person", and provide it with a name 'when born' / created / instantiated:
var Person = function(name) {
this.name = name;
};
Now we provide a behavior to the Person - class of instances:
Person.prototype.introduceYourself = function() {
console.log("Hi, my name is " + this.name);
};
Creating susan and mark and ask them to introduce themselves would then go like this - notice the 'politically not so correct all lower case beginning, but convention complying useful distinction of instance vs. class casing:
var susan = new Person("Susan");
var mark = new Person("Mark");
susan.introduceYourself(); // ---> console shows: Hallo, my name is Susan
mark.introduceYourself(); // ---> console shows: Hallo, my name is Mark
Note that we had to make the definition only once as a class, but get multiple instances with same state - .name - and behavior - .introducesYourself().
Unfortunately, the way (most) modules are built and used is the way of singleton. Singleton means: there can exists only / exactly (math.) one instance of that class (so not really a class, because what is a class with one member...). Bit what do you do when you have multiple sensors, and the sensor is made available / connectable via a module that is thinking 'in singleton' (only)?
Sometimes, you get away by storing the module in a variable and invoke it several times with connect. This works though only when the module is built in a particular way and returning the instance from the constructor function. (Depending how the require("moduleName") is implemented (with or without caching), instead of storing the module reference in a variable, you just repeat the require(...) with no significant performance penalty.)
You can instantiate objects within other object instantiations... nothing wrong with that. It just creates dependencies - which you may have anyway. A less intertwined approach would be to create the containing object with null values for the contained objects first, and then assign the object instance to in a separate step, where you compose the complete containing object (or you go very sophisticated and use a micro / pico container supporting IoC / DI ... pico has nothing to do with Espruino Pico except that it is a smaller version of a bigger thing...)
In order to access properties - state and behavior - of a contained object, you can call the objects nested - containingObj.containedObj1.getTemperature(); - which is not the best from an oo point of view. You rather add a facade or delegate method .getTemperature() - ContainingObj.prototype.getTemperature = function() { return this.containedObj1.getTemperature(); }; - to the containing object. With that you can hide the implementation of ContainingObj and you can change it at a later time without having to change where and how it is used (so far).
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 is currently a conversation going in that respect - Serial.on() issues - which is actually more a about this, context classes, objects (instances of classes), functions, methods, callbacks, etc.
Javascript has a bit a quirky looking way of instantiating an object from a given class: issuing
var inst1 = new MyFunction()
makesMyFunction()
a class definition - or constructor function - that defines - and constructs - (usally the state of) an object - hence the convention of starting Uppercase. Issuing it a second timevar inst2 = new MyFunction()
creates actually a second, different instance - but with the same properties - state (and behavior).Invoking a capability, function, or behavior of that class of objects is then more suitably called invoking a method. Defining methods (behavior) is done by assigning functions to the prototype of the (state) defining function.
To make it more obvious, lets, call the "MyFunction" a "Person", and provide it with a name 'when born' / created / instantiated:
Now we provide a behavior to the Person - class of instances:
Creating susan and mark and ask them to introduce themselves would then go like this - notice the 'politically not so correct all lower case beginning, but convention complying useful distinction of instance vs. class casing:
Note that we had to make the definition only once as a class, but get multiple instances with same state - .name - and behavior - .introducesYourself().
Unfortunately, the way (most) modules are built and used is the way of singleton. Singleton means: there can exists only / exactly (math.) one instance of that class (so not really a class, because what is a class with one member...). Bit what do you do when you have multiple sensors, and the sensor is made available / connectable via a module that is thinking 'in singleton' (only)?
Sometimes, you get away by storing the module in a variable and invoke it several times with connect. This works though only when the module is built in a particular way and returning the instance from the constructor function. (Depending how the require("moduleName") is implemented (with or without caching), instead of storing the module reference in a variable, you just repeat the require(...) with no significant performance penalty.)
You can instantiate objects within other object instantiations... nothing wrong with that. It just creates dependencies - which you may have anyway. A less intertwined approach would be to create the containing object with null values for the contained objects first, and then assign the object instance to in a separate step, where you compose the complete containing object (or you go very sophisticated and use a micro / pico container supporting IoC / DI ... pico has nothing to do with Espruino Pico except that it is a smaller version of a bigger thing...)
In order to access properties - state and behavior - of a contained object, you can call the objects nested -
containingObj.containedObj1.getTemperature();
- which is not the best from an oo point of view. You rather add a facade or delegate method.getTemperature()
- ContainingObj.prototype.getTemperature = function() { return this.containedObj1.getTemperature(); }; - to the containing object. With that you can hide the implementation of ContainingObj and you can change it at a later time without having to change where and how it is used (so far).