Objective
Start with the page Installation of Objective.js
The Objective class is at the root of all the classes of Objective.js.
An instance of Objective can delegate the execution of different methods to a another instance, transfer the execution of a method to another instance which can automatically dispatch it, transfer the execution of a method to another instance which can directly respond to it or dispatch it automatically, notify to transfer the execution of a method to listeners which can directly respond to it or automatically dispatch it.
An instance of Objective can clone itself.
NOTE: The classes Undo and Validator are independent and can be used without Objective.js in any project in JavaScript .
- function Objective() {
- }
Creates an instance of the class Objective.
- Objective.prototype.clone = function() {
- return Object.assign(Object.create(this), this);
- };
clone
returns a new instance identical to this
.
IMPORTANT: clone
copies the values of all the properties of this
.
If a value is a reference to an object, the clone will share the reference.
See the article Object.assign() on the website MDN Web Docs.
- Objective.prototype.delegate = function(f = null, ...args) {
- let d = this._delegate;
- if (f === null)
- return d;
- if (d === undefined)
- return undefined;
- if (! (f in d && typeof d[f] === 'function'))
- return undefined;
- return d[f](...args);
- };
Returns the result of the execution of the function f
with the arguments args
following f
by the delegate of this
.
If this
doesn't have a delegate or if the delegate of this
doesn't have the function f
, delegate
returns undefined
.
If f
is null
, delegate
returns the delegate of this
.
- Objective.prototype.setDelegate = function(d) {
- if (! (d === null || (typeof d === 'object')))
- throw new TypeError();
- this._delegate = d;
- return this;
- };
setDelegate
initializes the property delegate of this
to d
.
- Objective.prototype.hasListener = function(l) {
- return this._listeners !== undefined && this._listeners.indexOf(l) != -1;
- };
hasListener
returns true
if the instance l
is in the list of listeners of this
, otherwise false
.
- Objective.prototype.addListener = function(l) {
- if (this._listeners === undefined)
- this._listeners = [l];
- else if (this._listeners.indexOf(l) == -1)
- this._listeners.push(l);
- return this;
- };
addListener
adds the instance l
to the list of listeners of this
.
- Objective.prototype.removeListener = function(l) {
- if (this._listeners !== undefined) {
- let i = this._listeners.indexOf(l);
- if (i != -1)
- this._listeners.splice(i, 1);
- }
- return this;
- };
removeListener
removes the instance l
from the list of listeners of this
.
- Objective.prototype.notify = function(f, ...args) {
- if (this._listeners !== undefined) {
- for (let l of this._listeners)
- l.forwardTo(f, ...args);
- }
- return this;
- };
notify
transfers the execution of the method f
with the arguments args
to the listeners of this
.
- Objective.prototype.forwardTo = function(f, ...args) {
- if (typeof this[f] === 'function')
- this[f](...args);
- else
- this.forward(f, ...args);
- };
forwardTo
runs the method f
of this
with the arguments args
.
If f
isn't a method of this
, forwardTo
automatically transfers its execution with forward
.
- Objective.prototype.forward = function(f, ...args) {
- };
forward
of Objective ignores the execution of f
and does nothing.
A subclass can code an implementation of forward
which transfers the execution of the method f
with the arguments args
to another instance, with forwardTo
to preserve the transmission between a series of instances. See the section Test.
Test
- function Calculator(helper = null) {
- this._accu = 0.0;
- if (helper)
- this.setDelegate(helper);
- }
- Calculator.prototype = Object.create(Objective.prototype);
- Object.defineProperty(Calculator.prototype, 'constructor', { value: Calculator, enumerable: false, writable: true });
- Object.defineProperty(Calculator.prototype, 'value', {
- get: function() {
- return this._accu;
- },
- set: function(n) {
- if (typeof n !== 'number')
- throw new TypeError();
- this._accu = n;
- }
- });
- Calculator.prototype.clear = function() {
- this._accu = 0.0;
- return this;
- };
- Calculator.prototype.add = function(val) {
- this._accu += val;
- return this;
- };
- Calculator.prototype.sub = function(val) {
- this._accu -= val;
- return this;
- };
- Calculator.prototype.mul = function(val) {
- this._accu *= val;
- return this;
- };
- Calculator.prototype.div = function(val) {
- this._accu /= val;
- return this;
- };
- Calculator.prototype.sqrt = function() {
- this._accu = Math.sqrt(this._accu);
- return this;
- };
- Calculator.prototype.clr = function() {
- this.delegate('clr');
- return this;
- };
- Calculator.prototype.sto = function() {
- this.delegate('sto', this._accu);
- return this;
- };
- Calculator.prototype.rcl = function() {
- this._accu = this.delegate('rcl');
- return this;
- };
- function CalculatorMemory() {
- this._mem = 0.0;
- }
- CalculatorMemory.prototype = Object.create(Objective.prototype);
- Object.defineProperty(CalculatorMemory.prototype, 'constructor', { value: CalculatorMemory, enumerable: false, writable: true });
- CalculatorMemory.prototype.clr = function() {
- this._mem = 0.0;
- return this;
- };
- CalculatorMemory.prototype.sto = function(val) {
- this._mem = val;
- return this;
- };
- CalculatorMemory.prototype.rcl = function() {
- return this._mem;
- };
- <?php head('javascript', '/objectivejs/Objective.js'); ?>
- <?php head('javascript', '/objectivejs/tests/Calculator.js'); ?>
Adds the tags <script src="/objectivejs/Objective.js">
and <script src="/objectivejs/tests/Calculator.js"></script>
to the <head>
section of the HTML document.
The test program creates a calculator with one memory, calculates the gold number and displays it, memorizes the result, clears the calculator, recalls the golden number in memory and displays it.
- const mem = new CalculatorMemory();
- const calc = new Calculator(mem);
Creates an instance of Calculator with one instance of CalculatorMemory as a parameter.
- calc.value = 5;
- calc.sqrt();
- calc.add(1);
- calc.div(2);
Computes (1 + sqrt(5)) / 2.
- console.log(calc.value); // 1.618
Displays the result.
- calc.sto();
- calc.clear();
Memorizes the result. Resets the calculator to 0.
- console.log(calc.value); // 0
Displays 0.
- calc.rcl();
Recalls the number in memory.
- console.log(calc.value); // 1.618
Displays the result.
- calc2 = calc.clone();
- console.log(calc2.value); // 1.618
- calc2.clear();
- console.log(calc.value); // 1.618
- calc2.clr();
- calc.rcl();
- console.log(calc.value); // 0
Creates a clone of the calculator and displays its value. Sets the value of the clone to 0 and checks that the value of the calculator hasn't changed. Sets the memory of the clone to 0. Recalls the value in memory of the calculator and displays its value. Since the calculator and its clone share the same instance of CalculatorHelper, it is set to 0.
Display the page generated by the file testObjective.phtml and check the trace in the console of the browser:
1.618033988749895
0
1.618033988749895
1.618033988749895
1.618033988749895
0
Check that the calculator and its clone share the same delegate:
calc2._delegate === calc._delegate
true
Add a clone
method to the Calculator class which clones the delegate of a calculator:
const clone = Objective.prototype.clone.call(this);
const delegate = this.delegate();
if (delegate)
clone.setDelegate(delegate.clone());
return clone;
}
Redisplay the page generated by the file testObjective.phtml and check in the trace in the console of the browser that the memory of the calculator isn't changed when the memory of the clone is cleared:
1.618033988749895
0
1.618033988749895
1.618033988749895
1.618033988749895
1.618033988749895
The calculator and its clone don't share the same delegate:
calc2._delegate === calc._delegate
false
- <?php head('javascript', '/objectivejs/Objective.js'); ?>
Adds the tag <script src="/objectivejs/Objective.js"></script>
to the <head>
section of the HTML document.
- function Ping() {
- }
- Ping.prototype = Object.create(Objective.prototype);
- Object.defineProperty(Ping.prototype, 'constructor', { value: Ping, enumerable: false, writable: true });
- Ping.prototype.echo = function(msg) {
- console.log(`[PING] ${msg}`);
- }
The method echo
of the class Ping displays [PING]
followed by the message msg
on the console.
- function Pong() {
- }
- Pong.prototype = Object.create(Objective.prototype);
- Object.defineProperty(Pong.prototype, 'constructor', { value: Pong, enumerable: false, writable: true });
- Pong.prototype.echo = function(msg) {
- console.log(`[PONG] ${msg}`);
- }
The method echo
of the class Pong displays [PONG]
followed by the message msg
on the console.
- function PingPong(pong) {
- this._pong = pong;
- }
- PingPong.prototype = Object.create(Objective.prototype);
- Object.defineProperty(PingPong.prototype, 'constructor', { value: PingPong, enumerable: false, writable: true });
- PingPong.prototype.forward = function(f, ...args) {
- this._pong.forwardTo(f, ...args);
- }
The method forward
of the class PingPong transfers the execution of all the methods to a Pong instance.
- function Router(ping, pong) {
- this._ping = ping;
- this._pong = pong;
- this._channel = this._ping;
- }
- Router.prototype = Object.create(Objective.prototype);
- Object.defineProperty(Router.prototype, 'constructor', { value: Router, enumerable: false, writable: true });
- Router.prototype.switch = function() {
- this._channel = this._channel === this._ping ? this._pong : this._ping;
- this.notify('routerSwitched', this);
- return this;
- }
- Router.prototype.forward = function(f, ...args) {
- this._channel.forwardTo(f, ...args);
- }
The method forward
of the class Router transfers the execution of all the methods to a Ping or a Pong instance.
The method switch
toggles the transfer of the methods between the Ping or the Pong.
switch
notifies the message routerSwiched to all listeners.
- function Listener(logger) {
- this._logger = logger;
- }
- Listener.prototype = Object.create(Objective.prototype);
- Object.defineProperty(Listener.prototype, 'constructor', { value: Listener, enumerable: false, writable: true });
- Listener.prototype.forward = function(f, ...args) {
- if (this._logger);
- this._logger.forwardTo(f, ...args);
- }
The method forward
of the class Listener transfers the execution of all the methods to a Logger instance.
- function Logger() {
- }
- Logger.prototype = Object.create(Objective.prototype);
- Object.defineProperty(Logger.prototype, 'constructor', { value: Logger, enumerable: false, writable: true });
- Logger.prototype.routerSwitched = function(sender) {
- console.log('ROUTER SWITCHED');
- }
An instance of Logger responds to a routerSwiched message by displaying ROUTER SWITCHED
on the console.
- const ping = new Ping();
- const pong = new Pong();
- const router1 = new Router(ping, pong);
Creates an instance of Router with an instance of Ping and an instance of Pong.
- router1.forward('echo', 'HELLO'); // [PING] HELLO
- router1.switch();
- router1.forward('echo', 'HELLO'); // [PONG] HELLO
Transfers the method echo
to router1
which transfers it to ping
which displays [PING] HELLO
.
Toggles router1
on pong
.
Transfers the method echo
to router1
which transfers it to pong
which displays [PONG] HELLO
.
- const pingpong = new PingPong(pong);
- const router2 = new Router(ping, pingpong);
Creates an instance of PingPong with an instance of Pong. Creates an instance of Router with an instance of Ping and an instance of PingPong.
- router2.forward('echo', 'HELLO'); // [PING] HELLO
- router2.switch();
- router2.forward('echo', 'HELLO'); // [PONG] HELLO
Transfers the method echo
to router2
which transfers it to ping
which displays [PING] HELLO
.
Toggles router2
on pingpong
.
Transfers the method echo
to router2
which transfers it to pingpong
which transfers it to pong
which displays [PONG] HELLO
.
- const logger = new Logger();
- const listener = new Listener(logger);
Creates an instance of Listener with an instance of Logger.
- router2.addListener(listener);
- router2.switch(); // ROUTER SWITCHED
- router2.forward('echo', 'HELLO'); // [PING] HELLO
Adds listener
to the list of listeners of router2
.
Toggles router2
on ping
which notifies the message routerSwitched to listener
which automatically transfers it to logger
which displays ROUTER SWITCHED
.
Transfers the method echo
to router2
which transfers it to ping
which displays [PING] HELLO
.
- const router3 = new Router(ping, router2);
Creates an instance of Router with an instance of Ping and an instance of Router.
- router3.addListener(listener);
- router3.switch(); // ROUTER SWITCHED
- router3.forward('echo', 'HELLO'); // [PING] HELLO
- router2.switch(); // ROUTER SWITCHED
- router3.forward('echo', 'HELLO'); // [PONG] HELLO
Adds listener
to the list of listeners of router3
.
Toggles router3
on router2
which notifies the message routerSwitched to listener
which automatically transfers it to logger
which displays ROUTER SWITCHED
.
Transfers the method echo
to router3
which transfers it to router2
which transfers it to ping
which displays [PING] HELLO
.
router2
on pingpong
which notifies the message routerSwitched to listener
which automatically transfers it to logger
which displays ROUTER SWITCHED
.
Transfers the method echo
to router3
which transfers it to router2
which transfers it to pingpong
which transfers it to pong
which displays [PONG] HELLO
.
Display the page generated by the file testObjectiveForward.phtml and check the trace in the console of the browser:
[PING] HELLO
[PONG] HELLO
[PING] HELLO
[PONG] HELLO
ROUTER SWITCHED
[PING] HELLO
ROUTER SWITCHED
[PING] HELLO
ROUTER SWITCHED
[PONG] HELLO
Comments