I have a problem with inheritance of two functions in node.js when i use require functions.
Here is my case:
function administrators () {
this.user = 'bob';
}
administrators.prototype.print_user = function () {
console.log(this.user);
}
/*******/
function helper() {}
helper.prototype = new administrators();
helper.prototype.change_administrator = function() {
this.user = 'john';
}
var h = new helper();
h.print_user();
h.change_administrator();
h.print_user();
As you can see here I have two functions:
administrations just has user variable and print_user function.
helpers inherits everything from administrators and then we add change_administrator which changes this.use declared in administrators().
Here is the question:
I want to have this functions (administrators and helper) in separated files, for example: administrators.js and helper.js.
Then I want to include these two files in index.js with require, and inherit administrators variables and functions to helper like I did in the example above.
P.S. I was looking for similar questions but there is nothing about that kind of inheritance.
You need to require administrators from within the helpers.js file.
administrators.js
function administrators () {
this.user = 'bob';
}
administrators.prototype.print_user = function () {
console.log(this.user);
}
module.exports = administrators;
helpers.js
var administrators = require('./administrators');
function helper() {}
helper.prototype = new administrators();
helper.prototype.change_administrator = function() {
this.user = 'john';
};
module.exports = helper;
index.js
var helper = require('./helpers');
var h = new helper();
h.print_user();
h.change_administrator();
h.print_user();
You would have to manually extend them in the class that did the requiring.
Extend here meaning "copy the methods and properties from one object to the other"
alternately have helpers require administrator directly
Related
I have a file called helpers.js in the 'helpers' folder. The contents are like below:
class Helpers {
constructor(config) {
if (this._singleton) {
throw new Error('A singleton has already been created.');
}
this._singleton = this;
}
/**
* Gets the singleton object.
* #returns {Helpers}
*/
static getSingleton() {
return this._singleton;
}
}
module.exports = Helpers;
Then in /helpers/user.js I want to get the helper's singleton instance.
This is my code:
const helpers = require('../helpers').getSingleton();
or
const Helpers = require('../helpers');
const helpers = Helpers.getSingleton();
The error I keep getting is:
TypeError: require(...).getSingleton is not a function
or
TypeError: Helpers.getSingleton is not a function
If I hover over Helpers in VSCode, I get this tooltip
And, whenever I hover over getSingleton() I get this tooltip:
So the path is correct, but it still gives me the errors.
The easiest way to implement the singleton pattern in JavaScript is to just not export the class at all, e.g.
class Helpers {}
let helper;
module.exports = function() {
if (!helper) helpers = new Helpers();
return helper;
};
// loaded with
var helpers = require('../helpers')(); // note the extra () to call it
or even better, since we aren't restricted to Java-like behavior, just skip the function entirely and do
class Helpers {}
module.exports = new Helpers();
// loaded with
var helpers = require('../helpers');
but then if all your module is exporting is a single instance of a class, there's very little reason to use a class in the first place. You might as well do
exports.helperMethodOne = function(){};
exports.helperMethodTwo = function(){};
exports.helperMethodThree = function(){};
// loaded with
var helpers = require('../helpers');
or
module.exports = {
helperMethodOne() {},
helperMethodTwo() {},
helperMethodThree() {},
};
// loaded with
var helpers = require('../helpers');
Your require statement is wrong, but its hard to tell you precisely the right syntax without knowing your environment.
const config = require('/path/to/file');
Is typical. So try:
const Helpers = require('../helpers');
You wrote '../helpers.js' in your screenshot, not '../helpers'
You get the error:
TypeError: require(...).getSingleton is not a function
Because require(...) resolves to something else, like null, and null.getSingleton is not a function.
Also, you cannot reference this meaninfully inside a static context. this ought to only be used for class instances, not static members.
You can do something like this to use it as Singleton.getInstance();
class Singleton {
static instance = new Singleton();
static getInstance = () => Singleton.instance;
constructor() {
throw new Error('Use Singleton.getInstance()');
}
}
module.exports = Singleton;
or even something more sneaky and use it as new Singleton()
class Singleton {
static instance;
constructor() {
if (!Singleton.instance) {
Singleton.instance = this;
}
return Singleton.instance;
}
}
module.exports = Singleton;
I learnt that you could mimic namespaces in JavaScript by scoping your classes / objects inside a function expression or an object literal. That way the containing object or function provides a namespace and scope for the contained.
But for those to work, all the contained objects have to be within the same file, right?
Because if I had two namespace / naming container objects with the same name in two different files, they would overwrite each other depending on the order in which I included the source files.
File1.js
var Automtomobiles =
{
function Wheel() { ... }
};
File2.js
var Automtomobiles =
{
function Car() { ... }
};
How do I span objects / class definitions across multiple files but keep them within a same namespace?
Make Automtomobiles as global object
File1.js
var Automtomobiles = Automtomobiles || {};
Automtomobiles.wheel = function() {
}
File2.js
var Automtomobiles = Automtomobiles || {};
Automtomobiles.car = function() {
}
To make them global you can use window.Automtobiles = function() or to define an static property to a type. You can use .prototype
function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
}
Person.prototype.nationality = "English";
console.log(new Person("john", "smith", 20, "red"));
Note how "English" is attached to each instance of Person after using the Prototype function
For your particular case, you can define Automtobiles then prototype it..
function Automtomobiles() {
};
Automtomobiles.prototype.wheel = function() { ... }
Automtomobiles.prototype.car = function() { ... }
Using pure javascript you could use the common notation that lot of libraries use. For one file:
var Automtomobiles;
(function (Automtomobiles) {
var Wheel = (function () {
function Wheel() {};
return Wheel;
}());
Automtomobiles.Wheel = Wheel;
})(Automtomobiles || (Automtomobiles = {}));
And the other file:
var Automtomobiles;
(function (Automtomobiles) {
var Car= (function () {
function Car() {};
return Car;
}());
Automtomobiles.Car= Car;
})(Automtomobiles || (Automtomobiles = {}));
Anyway, if you are open to use third party libraries, they could help you too. Long time ago I used Dojo declare feature, which manages the namespaces and class names for you, althoug I'm sure that at current exists more libraries to reach that.
In fact, you also could use Typescript, which is perfect to reach your goal and vey use to learn. The code generated by Typescript looks like the examples I posted above.
I'm learning reveal module pattern, and I'm trying to create a reusable function. (In my project, the function will make the page scroll. I don't think it's necessary to post the whole code here. I'm just putting the concept.)
The basic overview is, there's a function that will not return anything. There's no need for public variables. Here's the code. The questions are at the comments in the code:
JSFiddle
var MyModule = (function() {
// Is this the correct place to insert the
// variables that will be used throughout 'MyModule'?
var foo = 'foo',
foo2 = 'foo2',
param1 = null;
var MyModule = function(_param1) {
param1 = _param1;
logParam();
};
function init() {
foo = 'something';
}
function logParam() {
console.log(param1);
}
init();
return MyModule;
})();
var module = new MyModule('Some Paramater');
// Is this okay? Does it still follow reveal module pattern?
MyModule('Some Other Paramater');
// Or do I always have to do like this:
var module = new MyModule('Some Paramater');
The Module Reveal Pattern provides both private and public encapsulation.
Below an example with some explanatory comments.
More info about JavaScript pattern included Module Reveal Pattern can be found here
var myRevealingModule = (function () {
// below are private variables and functions that are not accessible outside the module this is possible thanks to a javascript closure
var privateVar = "Ben Cherry",
publicVar = "Hey there!";
function privateFunction() {
console.log( "Name:" + privateVar );
}
// below are public functions, they will be publicly available as they are referenced in the return statement below
function publicSetName( strName ) {
privateVar = strName;
}
function publicGetName() {
privateFunction();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
myRevealingModule.setName( "Paul Kinlan" );
console.log(myRevealingModule.greeting);// public
console.log(myRevealingModule.getName());// public
//console.log(myRevealingModule.privateFunction());// private, you cannot access it
Answering your comments:
// Is this okay? Does it still follow reveal module pattern?
MyModule('Some Other Paramater');
Yes, it's OK. If you want that your reveal module pattern "MyModule" must be selfclosing:
var MyModule = function(param1) {
var myPlublicFunction = function(){
}
return {
myPlublicFunction: myPlublicFunction
};
}(); //selfclosing
OR
// Or do I always have to do like this:
var module = new MyModule('Some Paramater');
If you want that, your reveal module pattern "MyModule" must be not selfclosing:
var MyModule = function(param1) {
var myPlublicFunction = function(){
}
return {
myPlublicFunction: myPlublicFunction
};
}; // not selfclosing
I hope it helps
I have two different js files that use the same module.
file1.js:
var mod1 = require('commonmodule.js');
mod1.init('one');
file2.js:
var mod2 = require('commonmodule.js');
mod2.init('two');
(both these files file1.js, file2.js are loaded inside my server.js file, they themselves are modules)
now in commonmodule.js:
var savedName;
exports.init = function(name)
{
savedName = name;
}
exports.getName = function()
{
return savedName;
}
I noticed that this savedName is always overridden dependent on who set it last.So it doesn't seem to work. How would I get a module to maintain state?
Note: I also tried to set savedName as exports.savedName in the commonmodule.js but it doesn't work either
You can just create a new instance every time the module is required:
commonmodule.js
function CommonModule() {
var savedName;
return {
init: function(name) {
savedName = name;
},
getName: function() {
return savedName;
}
};
}
module.exports = CommonModule;
file1.js
var mod1 = new require('./commonmodule')();
mod1.init('one');
console.log(mod1.getName()); // one
file2.js
var mod2 = new require('./commonmodule')()
mod2.init('two');
console.log(mod2.getName()); // two
modules in and of themselves are simple object instances. A single instance will be shared by all other modules (with the caveat that it is loaded via the same path). If you want state, use a class and export a constructor function.
example:
//Person.js
function Person(name) {
this.name = name;
}
module.exports = Person;
To use it:
var Person = require("./Person");
var bob = new Person("Bob");
Modules are not like classes/class functions; by default, mod1 and mod2 will refer to the same module due to caching. To keep track of per-instance state, you'll need a constructor function or something similar inside your module, e.g.
var mod = require('commonmodule.js');
var state = new mod.init('one');
Where init defines the stateful object. You could also have it return an object literal, in which case you wouldn't have to use new (e.g. var state = require('commonmodule.js').init('one');)
(This is assuming you want the module to have other, shared state in addition to the per-instance state; if that is not the case, Peter Lyons' method would be simpler.)
You could perhaps remove from cache your module. Like that:
file1.js:
var mod1 = require('commonmodule.js');
mod1.init('one');
file2.js:
delete require.cache[require.resolve(modulename)];
var mod2 = require('commonmodule.js');
mod2.init('two');
But I don't find it very convenient and clean.
But you could also clone it or make a small proxy.
Also you could create classes:
var savedName;
exports.obj = {}
exports.obj.prototype.init = function(name)
{
savedName = name;
}
exports.obj.prototype.getName = function()
{
return savedName;
}
Then :
var mod2 = new (require('commonmodule.js'))();
mod2.init('two');
I'm new to node.js (and stackoverflow) and haven't found an exact explanation of this.
This is probably a trial answer but hopefully it'll help someone else who's also transitioning from Python/other object oriented frameworks.
I've seen other articles about what the prototype concept is in js and then others that explain the module.exports of node.js.
I'm studying the Ghost CMS and they use both. I can't seem to pick out why they would choose one over the other in certain cases.
Any help is appreciated, even if it's pointing me to other links.
Actually they are interchangeable (in a way):
with prototype:
//module.js
function Person (name) {
this.name = name;
}
Person.prototype.sayName = function () {
console.log(this.name);
}
module.exports = Person;
//index.js
var Person = require('./module.js');
var person = new Person('John');
person.sayName();
with exports:
//module.js
exports.init = function (name) {
this.name = name;
return this;
}
exports.sayName = function () {
console.log(this.name);
}
//index.js
var Person = require('./module.js');
var person = Object.create(Person).init('John');
person.sayName();
The first example is more idiomatic for javascript, though.
With node.js, module.exports is how one exposes the public interface of a module.
/* my-module.js */
exports.coolFunction = function(callback) {
// stuff & things
callback(whatever);
};
This interface can then be consumed by another module after importing/requiring it:
/* another-module.js */
var myModule = require('my-module');
myModule.coolFunction(function(error) { ... });
Prototypes (a plain Javascript feature), on the other hand, are useful for defining shared properties and methods of objects instantiated from a constructor function.
function User() {
this.name = null;
}
User.prototype.printGreeting = function() {
console.log('Hello. My name is: ' + this.name);
};
var user = new User();
user.name = 'Jill';
user.printGreeting();
Cheers.