Inherit module in Javascript possible? - javascript

I have a module like this :
var myModule= {};
(function( exports ){
init();
exports.doSomething= function(){
return "test";
};
function init(){
initSubscribers();
initListeners();
initForAdmins();//just for the admin
}
//... a lot of functions that maybe doing things depends on if user is admin or normal user
})( myModule );
I have 2 web pages : "Normal page" use "myModule" for normal user and "Admin page" use "myModule" for admin.
Some parts of the module is used by both (normal and admin user) but some parts are specific to the type of user.
I would like to create 2 modules (myNormalModule and myAdminModule) that inherits from a general module (with shared function).
It looks strange to me to "inherit from a module".
My generalModule must be an object or it can be a module ?

You create object types and then inherit from them. You don't inherit from a module. One module can use another module in its own implementation, but that is not inheritance.
So, first create the object structure that you want to use (including inheritance if appropriate) and then, organize that into appropriate modules. And, in organizing your code into modules, a module could define an object type and could then export (e.g. share) that object type and then other modules could either use it or inherit from it. But, the module itself is just a code organizing structure, it isn't an inheritance structure.
So, I'd suggest you figure out your object hierarchy (including inheritance) before you worry about modules and once that is designed, you can then organize it into whatever appropriates modules. For example, if all your object types for this particular problem are pretty much always going to be used together, then they might all be put in one module together.
But, if some object types for this problem might be used by themselves, then it might make sense to break them into their own module for each of sharing only appropriate pieces.
If you have context that you want to share among modules, then there are several different ways to do that depending upon exactly what it is and how it's used. The context could belong to a base object that all other objects inherit from. Or, if the context is more global, it could be stored in one module and then exported to other modules that want access to it.

Related

In browsers + Node, what is the scope of a module?

I'm wondering what the scope of a module is in both browsers and Node. I'm specifically trying to understand whether a module-level variable is created once per app, or many times. Is a new instance of the module created on each import, or is it the exact same module shared across all imports? Many thanks!
There are several JS module flavours - ESM, CommonJS, AMD. Their common trait is that they are evaluated once on first import, at least under normal circumstances. Doing the opposite would make them inefficient for sharing data.
Exporting class instance is a common way to share one instance across the application without making a class a singleton.
The ways that can make a module be evaluated multiple times (intentionally or not) include having many copies of a module, different filename case on import in case-insensitive system, the modification of Node module cache.

JS: Best practice on global "window" object

Following a rapid-prototyping approach, I am developing an application in Marionette.js/backbone.js and heavily used the window-object to bind collections and views to the global stack (e.g. window.app.data, window.app.views).
Of course, it is always better (smoother!) to encapsulate objects in a single class and pass them as parameters where needed. However, this has some limitations when an app and its potential use-cases become really big. And as the data I deal with comes from an API and therefore would be anyway accessible to anybody interested, does that justify storing data in the window-object? Or are there other best-practices in ES6 (or especially Marionette.js) to achieve the same results, but in a more private manner?!
I already go into details about a simple namespacing pattern in JavaScript in another answer. You seem to be already close to this with window.app.data etc.
But it looks like you have a lot of misconceptions about how JavaScript works.
a namespace-based solution that integrates nicely with Browserify/AMD-modules
Then why not use RequireJS? Browserify? or Webpack? There's nothing that a global ridden spaghetti code can do that a modular approach can't do better.
such would be read-only
No. While not impossible to set an object property to read-only, you must explicitly do it with something like Object.seal or Object.freeze.
I do not want to attach objects to the namespace, but actual instances
JavaScript do not have "namespaces" as part of the language, it's just a pattern to scope all your code within literal objects (key-value).
You can put whatever you'd like.
const MyNamespace = {
MyType: Backbone.Model.extend({ /*...*/ }),
instance: new Backbone.Model(),
anyValue: "some important string",
};
Ideally, you would define the namespace within an IIFE to avoid leaking any variable to the global scope.
const app = app || {};
app.MyModel = (function(app){
return Backbone.Model.extend({
// ...
});
})(app);
[...] data I deal with comes from an API and therefore would be anyway accessible to anybody interested
Even if the data is contained within a module that do not leak to the global scope, anybody can access the data. That's how JavaScript works, it's in the user's browser, he can do whatever he wants with the code and the data.
does that justify storing data in the window-object?
No.
Or are there other best-practices in ES6
ES6 has nothing to do with the architecture and patterns you take for your app.
but in a more private manner?!
Like I said earlier, privacy in JavaScript can't be expected.
[encapsulate objects in a single class and pass them as parameters where needed] has some limitations when an app and its potential use-cases become really big.
That's just incorrect. It's the other way around. Software patterns exist solely to help alleviate any limitations that arise as a project grows in scope.
There are multiple patterns you can use that will help deal with the complexity of a bigger app, like:
Modular approach with components
Dependency injection
Service containers
Factories
Events
etc.
I didn't read specifically this book, but JavaScript Design Patterns seems to be a good way to learn more and it demonstrates specific implementations of software patterns in JS.

Module Exports best practices for ECMA6 class

In my nodejs project extensively using the ECMA 6 classes, my question is with regards to exporting this classes.
There are 2 ways for instance:
class MyClass{
constructor(myAttr){this._DB =DB;}
someMethod(){DB.save()}
}
module.exports=Myclass;
Second way:
class MyClass{
constructor(){}
someMethod(obj){var DB =require('DB'); DB.save(obj)}
}
module.exports=new Myclass();
First one relies on the .js to instantiate the class and pass on the variables(DB) While object creation of MyClass, there would however be as many objects created as many requests are coming in of MyClass. However the Class level attributes of MyClass(Db in this case) would not be duplicated.
Second Approach instantiates MyClass but the variable DB is created as many times as the call to SomeMethod is made.
Third approach not so neat is to create global variable for DB and use it :
'use strict'
const DB = require('DB')
class MyClass{
constructor(){}
someMethod(obj){DB.save(obj)}
}
module.exports=new Myclass();
I would like to know what approach is more suitable and in what scenarios.
Best,
-V
Your first approach exports the class and allows anyone who loads your module to create as many instances of your object as they would like.
Your second approach exports only a single object, no matter how many separate callers all load your module. This is called a singleton and all customers of this module would share the same single object.
Your third approach is not much different in practical usage from the second approach. It is also a singleton in that all callers get access to the same object. Your variable DB is not a global. It's a module-level variable that is only accessible to the code inside this module. The third approach has the advantage that the DB variable cannot be messed with by outside code, whereas in your first approach, that data is stored in the object's instance data and can be accessed by anyone.
The first two options offer very different features (freely create many objects vs. singleton). YOU have to decide whether you want to export the class so others can create their own instances or whether you want to export only a single object and all callers share the same object. This is an architectural choice for you to make and we cannot make it for you because it depends only upon what you want to export and what functionality you want the customers of this module to have. There are reasons to want all users of the module to share the same object and there are reasons for each user to be able to instantiate their own object. You have to decide which you want.

Avoiding re-evaluation and dynamically unloading objects called with `require`

i'm studying how nodejs module system works.
I've found so far this literature:
https://nodejs.org/api/modules.html
http://fredkschott.com/post/2014/06/require-and-the-module-system/
http://www.bennadel.com/blog/2169-where-does-node-js-and-require-look-for-modules.htm
It helps me to understand a few points however is still have these questions:
If i have a expensive resource (let's say database pooling connection) inside a module, how can i make sure that by requiring the module again i am not re-evaluating the resource?
How can i dynamically unload a disposable resource once i already called the 'require' on it?
It's important because i have some scenarios that demands me to make sure that i have a single instance of database pool. because of this i'm exporting modules which are able to receive parameters instead of just require the expensive resource.
Any guidance is very appreciated.
Alon Salont has written an EXCELLENT guide to understanding exports in NodeJS (which is what you're accessing when you call require()) here:
http://bites.goodeggs.com/posts/export-this/#singleton
If you study the list of options for what a module can export, you'll see that the answer to your question depends on how the module is written. When you call require, NodeJS will look for the module loaded in its cache and return it if it already had it loaded elsewhere.
That means if you choose to export a Singleton pattern, are monkey-patching, or creating global objects (I recommend only the first one in your case), only ONE shared object will be created / will exist. Singleton patterns are good for things like database connections that you want to be shared by many modules. Although some argue that "injecting" these dependencies via a parent/caller is better, this is a philosophical view not shared by all, and singletons are widely used by software developers for shared-service tasks like this.
If you export a function, typically a constructor, require() will STILL return just one shared reference to that. However, in this case, the reference is to a function, not something the function returns. require() doesn't actually CALL the function for you, it just gives you a reference to it. To do any real work here, you must now call the function, and that means each module that requires this thing will have its own instance of whatever class the module provides. This pattern is the more traditional one where a class instance is desired / is the goal. Most NPM modules fit this category, although that doesn't mean a singleton is a bad idea in your case.

requireJS : How to structure Javascript for an entire site?

I have 3000+ lines of javascript that I need to get into a sensible/maintainable structure. I have chosen to use requireJS as it has been recommend to me by a few people. I have a bunch of variables that are used throughout the application and need to be available everywhere. I also have a bunch of functions that need to be available everywhere. Apart from these two dependencies most of the code can be divided off into their own modules.
I am having trouble understanding how to manage my main variables so that if one module of code makes changes to the variables the rest of the JS modules will see that change. I think I need to see a few examples that demonstrate how requireJS is intended to work on a larger scale that the examples in the documentation.
If anyone is an experienced requireJS user I would love the hear your tips!
The whole point of RequireJS is to avoid the need for these global variables and global functions.
Can't you wrap those globals into a module, then depend on it in your other modules?
For example, a RequireJS modularized Dojo may be something like:
dojo/cache module
dojo/string module (requires dojo/cache)
dojo/date module (requires dojo/string)
dojo/cookie module (requires dojo/string)
:
:
dojo module (requires everything above, make them all into sub-objects, say, e.g. dojo.cache, dojo.string, dojo.date etc.)
user module #1 (requires dojo)
user module #2 (maybe only requiring dojo/string)
RequireJS gives you better options for encapsulating modules, but it doesn't change Javascript itself at all. As a transition strategy, you can still define your globals inside the function block. Depending on the module that contains these definitions will ensure that it has run before the dependent modules.
Next step would be to assign those methods to an object other than window, and then use that object through the variable received from RequireJS module dependency.
Hopefully by the time you've done this, you might have some insight into a cleaner solution. I refactored (and still am) a single-file project into several files, including optional plug-ins, although I did most of it before adding RequireJS to the mix.
See the RequireJS documentation:
Defining a module
Definition Functions with Dependencies
If the module has dependencies, the first argument should be an array of dependency names, and the second argument should be a definition function. ... The dependencies will be passed to the definition function as function arguments
define(["./cart", "./inventory"], function(cart, inventory) {
// ...
return { ... };
}
);
So I think you can define() your main module like all other modules and make the submodules depend on that main module. Then the module object is passed as an argument to the definition function of a submodule. You don't have to use global variables.
If you want to share information between modules, attach the information to the module object, and have the other modules rely on that module, and check its property.
If you have existing code, you can assign to window.x to provide a global x while you are cleaning it up.

Categories

Resources