Reputation: 39
For the class Engine, "start" and "stop" are two public methods
which internally calls "ignitionOn" and "ignitionOff".
After "start" is called the private method
sets a variable "ignitionIndicator
" to "true
" on the engine instance
and "stop
" sets it to "false
".
However that is not happening. Something is going wrong since the "ignitionIndicator" value is always "undefined". I have to keeping the following in mind.
(i) Visibility of the methods should be as it is.
(ii) I CAN NOT set the variable directly from the public methods
. The variable should be only and only set from within the private method
.
function Engine() {
function EngineConstructor() { };
// publicly accessible methods
EngineConstructor.prototype.start = function() {
ignitionOn();
};
EngineConstructor.prototype.stop = function() {
ignitionOff();
};
// private methods
function ignitionOn() {
// does other things and sets this to true
this.ignitionIndicator = true;
};
function ignitionOff() {
// does other things and sets this to false
this.ignitionIndicator = false;
};
return new EngineConstructor();
};
var e = new Engine();
e.start();
e.ignitionIndicator // undefined, should have been true
e.stop();
e.ignitionIndicator // undefined, should have been false
Upvotes: 0
Views: 103
Reputation: 1074138
You'd need to call those methods such that this
refers to an instance, for instance via Function#call
or Function#apply
, e.g.:
EngineConstructor.prototype.start = function() {
ignitionOn.call(this);
};
Or alternately, just pass the instance as an argument (procedural style):
EngineConstructor.prototype.start = function() {
ignitionOn(this);
};
// ...
function ignitionOn(instance) {
// does other things and sets this to true
instance.ignitionIndicator = true;
}
The pattern you're using in that code is very odd. You have a function, Engine
, which you use as a constructor (via new
) but which isn't a constructor (it returns something other than the instance created by the new
operator), and the object it returns is unrelated to the Engine
function — instead, it's an instance created by EngineConstructor
. Worse, it creates a whole new EngineConstructor
every time you call it. This is hugely inefficient; if you want to recreate all the methods for every instance, you can do so much more simply.
But I'd just revisit the entire structure so that you do get method reuse. If the goal is to have a constructor function which has access to private methods from prototype methods, the revealing module pattern (applied here to a single constructor) is the usual way to do that:
var Engine = function() {
// The constructor
function Engine() {
}
// Publicly accessible methods
Engine.prototype.start = function() {
ignitionOn.call(this);
};
Engine.prototype.stop = function() {
ignitionOff.call(this);
};
// Private methods
function ignitionOn() {
// does other things and sets this to true
this.ignitionIndicator = true;
}
function ignitionOff() {
// does other things and sets this to false
this.ignitionIndicator = false;
}
return Engine;
}();
var e = new Engine();
e.start();
snippet.log(e.ignitionIndicator);
e.stop();
snippet.log(e.ignitionIndicator);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Side note: Function declarations don't have a ;
after them. ;
is a statement terminator, and function declarations (such as those for ignitionOn
and ignitionOff
) are not statements.
Upvotes: 3