I am trying to implement Singleton in JavaScript where I use Node.js module.export and require().
My issue is that module.export so far for me returns new object from a class.
If I make it so that all classes are only available requiring them from Singleton class and not require() - then would I guarantee that I will have one instance only?
Because if all Other classes import from Singleton - how should I import Singleton?
In php no matter how many instances of Singleton you have - each share static properties. So if you make the instance static then all Singleton's no matter in which files they are invoked have the same memory and perform the same action.
However I have no idea what is the case with JavaScript
I also have another approach - If I make let instance variable at the start of the file and check if its empty at the end and if it isn't I make another instance instance = new MyClass() and then module.export = instance. Would this give me the same result?
For example what I currently do
class MyClass {
//some logic here
}
module.export = new MyClass()
What I think of doing but no idea if it is good or it will work
if(!instance){
let instance = 1;
}
class MyClass {
//some logic here
}
if(instance === 1){
instance = new MyClass()
}
module.export = instance
Also to make matter more complicated I have seen several versions of implementations
Here -> https://www.sitepoint.com/javascript-design-patterns-singleton/
There are 3 examples -
1.Old JS ECMA 2015 way with functions
2.ECMA 2016 with object literal instead of class
3.With classes but again Object.freeze and const
Now..these versions make use of Object.freeze which I am not familiar with and const variables...which I am also not perfectly sure how they work.
To recap (TL;DR) - What I want to do is a way so that if I require a class in 10 files with require("MyClass") I won't get 10 instances but only 1.
Does my way work properly and are the examples in the link with Object.freeze() and the use of const good working examples?Do I need an anctual Singleton class to do the job? Because solutions so far don't include one. And If I need - how do I pass that Singleton around so it has only one instance?
Node.js modules are singletons by default.
All imports referring to the same file would refer to the same object in memory. You don't have to do anything special
Related
I'm looking for something that will import the contents of an object to the global scope:
var y = {}
y.x = 5
//do some magic here
console.log(x); //5
I want to do this is so I can make an easy to use module with memorable function names without having to worry about things accidentally getting overridden by other modules.
Consider this example:
funModule = {};
funModule.washClothes = function(clothes){...}
funModule.walkDog = function(dogName){...}
//etc
funModule.UNITED_STATES_DEFICIT = ...;
Here I've created a module that has some useful functions and constants (implementations and values were replaced with "...").
I don't want my users to have to type out the module name every time they call function or use a constant. That would result with really messy code:
funModule.walkDog(funModule.UNITED_STATES_DEFICIT);
I could try it again by defining everything globally:
washClothes = function(clothes){...}
walkDog = function(dogName){...}
//etc
UNITED_STATES_DEFICIT = ...;
but if a different module has also defined the commonly named function washClothes we've got trouble. (in my actual case the commonly named function is run)
Removed from technical context, here is the problem I'm faced with:
Firstly I want to use simple and memorable names to make the module easy to learn and fun to use.
Secondly I don't want the easy names to make the module impossible to use with others. Especially as it grows, a lot of common names will be used. It would be great if the users could decide whether or not import the names directly.
Thirdly I realized as I'm typing this that what I'm describing is something that definitely already exists, in python. See http://effbot.org/zone/import-confusion.htm for more detail.
tl;dr How can python-like imports be done with javascript?
EDIT:
It seems there is not a universal way to do this.
Using Window won't work in all environments (but will work in any common browser).
Apparently ES6 Modules are not available to web browsers directly.
This question is different from this one because its not about Node.js. I was looking for a universal way to do it, but that doesn't seem possible, so I'll limit it to web browsers, (namely chrome, firefox, safari, opera, and maybe ie)
EDIT:
This general article about Scope could be useful for anyone with a similar question as mine: https://toddmotto.com/everything-you-wanted-to-know-about-javascript-scope/
Object.prototype.makeglobal=function(){
for(key in this){
if(window[key]){//replace window if youre not in a browser
//already exist, error handling
console.error(key+' already exist in window');
}else{
window[key]=this[key];
}}};
Use like this:
funModule.makeglobal();
//now you can
washClothes();
But this is bad as it pollutes the global object.
2.Your user should create his own namespace:
function(){
this.washClothes();
//more of his content
}.call(funModule);
3.You could also add a loader:
funModule.load=function(func){
console.log(func);
console.log(this);
func.call(this,this);
};
Now you can do:
funModule.load(function(fun){
this.washClothes();
fun.washClothes();
});
4.If youre concerned about readability you may use function chaining (?):
funModule.washClothes=function(){
//your code
return this;
}
now you can do:
funModule.washClothes("tshirts").washClothes("trousers").washClothes();
ES6 Modules are what you want.
If you will define your object as es6 module you could do this (using the names in your example):
import { washClothes } from "fun-module";
and then washClothes will be globally available on the file that imported it, just like you want.
Read about it here.
If you really want a magic solution like in the comment in your post and don't want to use ES6 and you run in the browser you can put it on the window object:
window.x = 5
In JavaScript, at least in a browser, global variables are properties of the window object: that is, window.x and x (where x is global) reference the same value. So, in theory, you could use Object.assign() to copy your object's properties to the window object making them global variables. This is roughly equivalent to globals().update(myobj.__dict__) in Python.
But just as import * is usually a bad idea in Python, so too this sounds like a bad idea, except even worse because window has a lot of other properties that you probably don't want to clobber.
After some additional research I found a way, without polluting the global namespace, to allow users to directly access module contents.
This solution allows the user to:
Write code that directly references the module's functions/properties
Define precedence if there are multiple modules written in this same style
Still access the module's functions/properties by module name*
*This feature comes with a catch
Here's the code
Module
funModule = {};
//This stuff is the arbitrary contents of the module:
funModule.washClothes = function(clothes){...}
funModule.walkDog = function(dogName){...}
//etc
funModule.UNITED_STATES_DEFICIT = ...;
//etc
//This part is necessary:
funModule.run(userApp)
{
for(key in this){
eval(key + " = " + this[key] + ";");
}
userApp();
}
The only way (that I could find) to dynamically define functions both in funModule.run's scope and in funModule is to use Eval. Using call, apply, or bind to manipulate scope would still require use of the this keyword and the whole point of this unusual style is to make client code as simple and non-repetitive as possible.
Client Code 1
function myApp()
{
washClothes(UNITED_STATES_DEFICIT);
}
funModule.run(myApp);
Here in the client code it is possible to directly access everything except for funModule.run. So the global namespace is kept clean but the user's code does not need unnecessary repetition.
Client Code 2
function myApp()
{
washClothes(UNITED_STATES_DEFICIT);
}
funModule.run( otherModule.run.bind({},myApp) ); //otherModule has precedence here
Assume otherModule is a different module that features the same run function. funModule will load its contents then call its first argument. The first argument will load otherModule's contents, overriding anything from funModule with the same name.
Client Code 3
function myApp()
{
//directly access stuff from funModule
walkDog()
var big = UNITED_STATES_DEFICIT * 3.14;
//explicitly access stuff from specific modules
clothes = new otherModule.Clothes();
funModule.washClothes(otherModule.washClothes(clothes));
}
funModule.run(myApp)
This is the feature that makes use of eval necessary. The user can opt out of ambiguity of direct access. They can still access properties/methods by naming the module they come from.
But Why?
Some StackOverflow users were understandably concerned about the unusual set of constraints in the question, so I figured I would answer the following question:
Why don't you use a short alias for your module.
I tried to answer that question in this article, which pulls from this question and answer.
Which strategy of content architecture is best with unit testing in mind in TypeScript? Creating modules or classes?
module: moduleX.method1(); // Exported method
class: var x = moduleX.method1(); // Public method
best with unit testing in mind in TypeScript
If you have a function that doesn't depend on local state in a class .... then it should just be a function. No need to new SomeClass().foo() when you can foo()
Here you can use namespaces to offer a nice consolidation of different function into a single object : https://basarat.gitbooks.io/typescript/content/docs/project/namespaces.html and you get something like Utils.foo()
Be warned that I would prefer you just make a javascript module instead of a namespace : https://basarat.gitbooks.io/typescript/content/docs/project/modules.html
Most importantly have fun 🌹 As long as you are consistent and considerate of the next developer (leave comments / types) you can focus on the business logic.
I am a huge fan of the pattern of exporting a function as the main API of a JavaScript module. The reason is that in JS, a function can do basically anything a typical object can do and then some.
So this is typical for me:
function stuff() {}
function thing() { /* shortcut or default behavior */ }
thing.stuff = stuff;
module.exports = thing;
Now I've run into a situation where I want thing to behave like an instance of EventEmitter. And I don't want it to be a constructor.
Why? Well thing will really be along the lines of osPreferences, where calling it with some options will save data to the disk. It doesn't make any sense for users to instantiate it. There wouldn't be much use for new OSPreferences(), since your computer can only respect one set of preferences at a time.
Yet, changes can happen at any time, outside of my API. So there is a huge benefit to:
osPreferences.on('change', fn);
So the question is, what is a solid pattern for assimilating the behavior of an EventEmitter instance? Is it good enough to simply loop through all properties of a throwaway instance and copy them to the target function? Is it worth trying to mimic the inherited vs non-inherited setup? Are there any weird cases to take into account, given that the default this would be changed? Or is there a better, more sensible way?
Is it good enough to simply loop through all properties of a throwaway instance and copy them to the target function?
Yes. You don't even need to create a throwaway instance, you can just copy all EventEmitter.prototype methods onto your function, and then apply the EventEmitter to it.
function osPreferences() { … }
for (var p in EventEmitter.prototype)
osPreferences[p] = EventEmitter.prototype[p];
EventEmitter.call(osPreferences);
Is it worth trying to mimic the inherited vs non-inherited setup?
Not really. You insist on a singleton usage of your api, so you don't need any inheritance at all.
Are there any weird cases to take into account, given that the default this would be changed?
No, EventEmitter is coded quite defensively. Of course, your listeners might find it unusual…
Looping through and copying the methods and properties of the original object can fail depending on how EventEmitter is implemented. This approach is most likely to fail when there is heavy use of closures to hide properties.
The best approach, in my opinion, is to just directly set the prototype on your function instance. With your example, it would be something like:
var OSPreferences = function(){
// ...
};
Object.setPrototypeOf(OSPreferences, new EventEmitter());
ES6 class syntax is the most elegant solution for subclassing.
let EventEmitter = require('events'); //or `require('events').EventEmitter` in nodejs
Class osPreferences extends EventEmitter{
constructor(){
super();
console.log(this);
}
}
let osp = new osPreferences();
osp.on('change',function(){
console.log('osPreferences changed');
});
osp.emit('change');
Unfortunately, latest Node version does not support class syntax. You have to use iojs instead.
I have pretty big javascript class with bunch of methods stored in a single js file. This methods can be logically categorized like common methods, methods to filter data, navigation methods etc. Now I want this class being split by separate files each containing its own specific category methods and leaving all properties and common methods in the current file. Shortly speaking I need something that c# partial keyword is used for.
I would like to avoid using prototype as it means I have to type class name for every function like class.prototype.functionname = function () { ... } that does not look great.
UPDATE: This is how my class looks like
function MyClass() {
var self = this;
self.common = function() {...}
self.filterData = function() {...}
self.navigate = function() {...}
}
I do not know how to handle self properly with prototypes or extension
If your class does not use the prototype, you have little chance - it is one [too] big function. However, such big functions shouldn't exist anyway, are you sure you need it to be a class (with multiple instances)? Then you should move the functions to the prototype as far as you can. If not, a singleton would make more sense for you, which is essentially nothing more than an object literal. You also might have a look at the [revealing] module pattern, which is what you need (or one of its flavors) - the (sub) modules usually can be spread easily across different files, potentially using a dependency tracking loader.
If it does, you can easily split it up into the single parts. That does not mean you would need to repeat class.prototype.… = …, you can just use helper functions like extend
MyFavLibrary.extend(class.prototype, {
functionname: function functionname() {…},
…
});
or a simple IEFE-closure:
(function(proto) {
// even some place for static, private helper functions
proto.functionname = functionname() {…};
…
})(class.prototype);
I have a set of classes that work together (I'm coding in javascript).
There is one parent class and a number of child classes that are instantiated by the parent class. I have a number of clients of these classes that each need to add one or more methods to the parent or child classes.
Rather than having each client inherit from these classes, which is doable but messy because of the child classes, I am having these clients pass functions into the parent class when they instantiate the main class.
The main class creates the methods dynamically and the clients can call the methods like they were there all along.
My questions are:
is this a sensible thing to do?
what would the design pattern be for what I am doing?
The strategy pattern is for situations where you get your 'strategy' at runtime. might be applicable here. Strategy in this case is a class that conforms to a behavior, i.e. has a method like 'execute' or whatever.
The decorator pattern also might apply. It is also a runtime pattern, but augments the class it is decorating at the method level.
So the Strategy pattern is good if you are choosing a class dynamically, and Decorator is good if you are only changing out the method implementation at runtime.
(I took the decorator part of this answer with permission from ircmaxell)
I must admit that patterns aren't my "thing" - but you can do exactly what you want to in javascript. It is how all of the frameworks accomplish that sort of things "extending" child "classes" (there are no classes in javascript).
If you are in the pure javascript world, you want to use:
foo.prototype.bar = function() {};
So you can call bar on any foo, and bar only exists in memory once - that is the same function is referenced in memory through every foo object. So be careful with any variables you might be referencing outside that scope.
Each library has their own plugin architecture to accomplish roughly the same goal (and they take care of some of the messiness/danger in prototype)
You should provide some code, so that we can get a feel for what exactly you're talking about.
As you haven't: I can only guess that you're not making use of prototypes. Prototypes would be the "correct" design pattern for "object-oriented" JavaScript.
When you add a function/property/whatever to the prototype of an object in JavaScript, all instances, new and old receive the function/property/whatever on their prototype.
Extending prototypes in JavaScript is very simple, and should never become messy. If it does, it probably means you're over-complicating it.
As hvgotcodes says, you are describing the Strategy Pattern, the way you would do this for your specific case, is not to use prototypes (thereby affecting all objects of your class.)
Instead you'd provide a member that accepts a function as it's value.
e.g.
function MyClass() {
this.myFunction = defaultFunction;
this.defaultFunction = function() {
// do something by default.
alert("using default");
}
this.doFunction = function() {
// something that calls myFunction.
this.myFunction();
}
}
---8< snip --------
// later on...
t = new MyClass();
t.doFunction(); // output 'using default'
t.myFunction = function(){
// do something specific with this instance, when myFunction is called.
alert("customized for this instance.");
}
t.doFunction(); // output 'customized for this instance.'