unable to call static function on ES6 class - javascript

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;

Related

Javascript class in closure

I'm writing a JavaScript closure that contains classes and looks a bit like this:
// myClosure.js
var myClosure = (function() {
class myClass {
constructor(val) {
this.myValue = val;
}
myFunc() {
console.log("myClass says: " + this.myValue);
}
}
this.myClass = myClass;
});
I'd like to 'import' this closure into another JavaScript file and instantiate a myClass. I tried this:
// myApp.js
$.getScript('myModule.js', function(myClosure) {
var myClassInstance = new myClosure.myClass(7);
}
but I get an error claiming that myClosure.myClass is not a constructor.
Can someone please point to a simple example, or a better way of doing this altogether?
Couple of things, myClosure returns nothing, so you will never be able to access it. In your example you could just return this.
Next, you have not executed the closure, you can do this by putting () at then end to make it into an IFFE..
Below is an example.
// myClosure.js
var myClosure = (function() {
class myClass {
constructor(val) {
this.myValue = val;
}
myFunc() {
console.log("myClass says: " + this.myValue);
}
}
this.myClass = myClass;
return this; //add this
}()); //and <- () that.
var myClassInstance = new myClosure.myClass(7);
myClassInstance.myFunc();
this doesn't work anything like that
myClosure is a function which doesn't create a closure
The first argument to the callback to getScript is a string containing the script. It isn't a value from the script.
To get values from it, you need to access a global.
Typically, if you were using jQuery.getScript, it would look something like this:
// myModule.js
class myClass {
// etc
}
// main.js
$.getScript('myModule.js', function () {
const myInstance = new myClass(7);
});
Modern code would tend towards using ES6 modules:
// myModule.js
class myClass {
// etc
}
export default myClass;
// main.js
import myClass from "./myModule.js";
const myInstance = new myClass(7);
// HTML
<script type="module" src="main.js"></script>
… although that sacrifices Internet Explorer support, in which cases you would want to look at using a bundler tool like Webpack.
you need to export this function first to include it in another javascript file.
if you are using node simply use module.exports = function name or for es6 you can use export default
and in another file simply import it

singleton pattern - require(...) is not a function

I've set up a class with a singleton design like this.
The file is called helpers.js.
class Helpers {
//Code
}
let singleton;
/**
* #returns {Helpers}
*/
const getHelpers = (options) => {
if (!singleton) {
singleton = new Helpers(options);
}
return singleton;
};
module.exports = getHelpers;
That means the first time, I'll have to do
const helpers = require('./helpers')(options);
And every time after, I just have to do:
const helpers = require('./helpers')();
For some reason I keep getting
TypeError: require(...) is not a function
My require requires the right file, and my VSCode autocorrect says that requiring it will give me a function that returns a Helpers, and that require(''')() will return a Helpers.
I have no idea what can be wrong.
EDIT
When I inspect the return value of require('./helpers') it's an object with some basic functions.

How can a module in node.js maintain state?

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');

Semantic JavaScript singleton with constructor

So I'd like to have a class called client which will be the base of a video game I'm writing in JavaScript.
client should be a class that there can only be one instance of, but its first creation should be set by myself at a specific event, like when the user clicks the "start" button.
I made myself a singleton class and I'm starting it unload just for testing:
// Singleton class for the client
var client = (function() {
// Public methods
var _this = {
construct: function() {
delete _this.construct;
_this.director = new lime.Director(document.body, window.innerWidth, window.innerHeight); // Setup the rendering engine
}
}
return _this;
})();
// Fire when dependencies are loaded
window.onload = client.construct;
The problem:
But I intend for this to be an open source project and on the last line client.construct seems to be a highly unusual convention. How can I write my singleton class so that it will be constructed with new Client and can never be constructed again?
Firstly: are you sure you really want to do this? For most simple cases, you're probably better off not bothering with a prototype or using the new keyword at all, and instead just writing an object literal with the properties and methods you want - or creating an object with a one-off function if slightly more complicated construction logic is required. Simplicity is good.
I guess there are a couple of situations in which you might want to create a 'traditional' singleton in JavaScript, though - like to delay instantiation, or if you're using classical inheritance involving your singleton class's prototype.
In that case, you might want to try this approach, based upon bfavaretto's, in which the user of the class is expected to get a Client object by calling Client.getSingletonInstance() instead of new Client(), and the instantiation of a Client via new happens inside the getSingletonInstance() method.
var Client = (function() {
// Our "private" instance
var instance;
// The constructor
function Client() {
// If it's being called again, throw an error
if (typeof instance != "undefined") {
throw new Error("Client can only be instantiated once.");
}
// initialize here
// Keep a closured reference to the instance
instance = this;
}
// Add public methods to Client.prototype
Client.prototype.myPublic = function() {
}
Client.getSingletonInstance = function() {
if (typeof instance == "undefined") {
return new this();
}
else {
return instance;
}
}
// Return the constructor
return Client;
})();
var c1 = Client.getSingletonInstance();
var c2 = Client.getSingletonInstance();
console.log(c1 == c2); // true
I prefer this way, because it seems to me that having the user of the class call new but not actually get a new object is misleading.
http://jsfiddle.net/hBvSZ/3/
You can use the same pattern you would use in a regular object-oriented language: store the instance in a "private" or "static" property (I'm quoting those terms because they don't precisely apply to JavaScript). In code, that would be something like this, using a "private" property to store the instance (a "static" property would be a property of the constructor):
var Client = (function() {
// Our "private" instance
var instance;
// The constructor
function Client() {
// If it's being called again, return the singleton instance
if(typeof instance != "undefined") return instance;
// initialize here
// Keep a closured reference to the instance
instance = this;
}
// Add public methods to Client.prototype
Client.prototype.myPublic = function() {
}
// Return the constructor
return Client;
})();
var c1 = new Client();
var c2 = new Client();
console.log(c1 == c2); // true
http://jsfiddle.net/hBvSZ/
Something like this:
var Client = (function ClientClass(){
var instance;
// Constructor
function Client() {
if (instance) throw 'Already instantiated';
this.director = new lime.Director(...);
instance = true;
}
Client.prototype = {
// Public methods
};
return Client;
}());
This may be what you want:
var initialized = false;
function initialize() {
if (!initialized) {
window.client = new Client();
initialized = true;
}
}
window.onload = initialize;
You don't. In strongly-typed languages, singletons are made by having private constructors and exposing a static property that contains the only instance of the class. The only thing you may do to prevent instantiating a second time is to throw exceptions but that is even poorer design. You may however delay instantiating your object:
// A wrapper function
var client = (function () {
var client = function() {
// Actual class
}
var instance = null;
// Property to return the instance
Object.defineProperty("instance", {
get: function () {
if (!instance) { instance = new client(); }
return instance;
}
}
return client;
})();
This is my favorite pattern for singleton instance, it is simple and straightforward:
var mySingleton = new function() {
// ...
}
So you can do:
var myClient = new function() {
this.director = null;
this.initialize = function() {
// Setup the rendering engine
this.director = new lime.Director(
document.body,
window.innerWidth,
window.innerHeight
);
}
}
window.onload = myClient.initialize();
Source: Singleton pattern by Alexander Podgorny

Node.js prototypal inheritance with require

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

Categories

Resources