I'm about to start building a JS library that will have multiple modules. Let's suppose the library is called Library, and two modules will be called One and Two. I'd like for end users to be able to call the library in two different ways:
Library.One.somefunction(params)
or
somefunction(params)
Basically, I want to give the end users the option of including a namespace or not. Is there a good way to do this? Also, is there a good way to do this if I also want to provide a minified version of the library? This library is something that I could end up in Node.js; for now, I'm going to use it myself, but I want to design it in such a way that it's not too hard to turn in to a sharable project in the future.
Any references you can point me to would be great, thanks!
If you're using Node.js you could leverage the CommonJS module system.
math.js (your library)
exports.add = function() {
for (var i = arguments.length; i--;) {
sum += arguments[i];
}
return sum;
};
program.js (someone using it...)
var MyMath = require('math');
console.log(MyMath.add(1, 2)); // 3
// ... in different ways
var add = require('math').add;
console.log(add(1, 2)); // 3
The basic idea behind making a "namespace" optional is to assign the functions to the global scope, which is the window object:
window.somefunction = Library.One.somefunction;
You can write an include function that works similar to other languages:
var include = function (library, p) {
if (!p) {
for (var prop in library) {
if (library.hasOwnProperty(prop)) {
window[prop] = library[prop];
}
}
} else {
window[p] = library[p];
}
};
Then just do, as required:
include(Library.One);
Or use particular functions only:
include(Library.One, 'somefunction');
Warnings:
Executing the functions without the dot notation (One.somefunction) will cause the this keyword to refer to window rather than Library.One. This isn't a problem if you don't use this at all. If you have data to share to between functions then you can do so using closure scope instead of this:
var Library = {};
(function () {
// I'm a closure, I have local scope
var sharedData = "I'm shared but private to this scope";
Library.One = {};
Library.One.funcOne = function () {
alert(sharedData);
};
Library.One.funcTwo = function () {
sharedData += "!";
};
}) ();
Others have well-advised not to make your methods global. This is because once it is global, it is global for all files, and therefore likely to conflict with other code. What you can do is modify the import function above to create a new object, and assign everything to that object before returning it. Then files that need shortcuts to particular libraries can do:
(function () {
var _ = include(Library.One); // This stays within this scope
_.somefunction();
})();
well, i don't know what you mean by "good way".
First of all, the whole purpose of a namespace is to collect variables that are related and not scatter them all around your public namespace.
Personally I wouldn't use such a thing, but you could loop through your namespace's objects and attach them to the window :
for(var i in Namespace)
if(Namespace.hasOwnProperty(i))
window[i] = Namespace[i];
You could do this pretty easily, but are you certain you want to make all the methods global properties?
You could implement it like this (very simplified):
(function( window, undefined ) {
// Your code setting up namespaces
var Library = {One:{},Two:{}};
// function for adding library code to both namespaces.
// Could be modified to accept an Array of functions/names
function addToLibraryOne( id, fn ) {
window[id] = Library.One[id] = fn;
}
// add a function
addToLibraryOne( "somefunction", function( params ) {
// function code
});
window.Library = Library;
})( window );
I'd wonder if you really want to pollute the global namespace like this.
At the very least, I'd make the global properties an option, then only have the function add those if that option is selected.
Well, the second one means that you also want the functions and object and whatever in your modules to be in the global scope. Entirely possible of course, but so against best practices as to be somewhat abhorrent.
For the first part, just declare your Library namespace globally:
var Library = {};
and then start populating it with your modules:
Library.One = {};
Library.Two = {};
and then start adding the functionality to those modules.
(function($) {
var $.froobString = function(s) { .... };
...etc...
})(Library.One);
(Here I've done it as a self-executing anonymous function that passes in Library.One as $.)
To convert all that to globals, have a routine like this:
var convertToGlobals = function(module) {
for (name in module) {
window[name] = module[name];
}
};
convertToGlobals(Library.One)
But then again I'd advise against it.
I might be wrong about this (so this might get downvoted, but I want this evaluated), but I think you are setting up a contradiction with the requirements
1) I want to use namespaces
2) I want to be able to access namespace functionality without the namespace.
basically 2 is "I dont want namespaces".
For implementation, you could just define a bunch of functions globally that route into the namespace, but then why have the namespace to begin with?
Related
I am trying to make some modifications to a Node.js app that I forked, what I am trying to do is call a function within another one.
I have attempted a crack at this by simply calling the method as follows but I'm not really that familiar with Node.js so I'm not sure I'm doing it right.
'use strict';
/*
* initalize the class
*/
function MessageBot(bot, user, cache) {
this.bot = bot;
this.user = user;
this.cache = cache;
}
/*
* perform commands
*/
MessageBot.prototype.librarySearch = function(searchText) {
var self = this;
// call SOS function - this is the bit that doesn't work
MessageBot.prototype.callSos(somenumbervar);
}
MessageBot.prototype.callSos = function(number) {
// do something else here
var self = this;
var commandList = self.cache.get('commandList');
}
Remember that this ostensibly inherits the prototype (directly or indirectly). Therefore, you can just do this.callSos(somenumbervar).
If you want to reach the method through the prototype, you have to tell it what this is. With your current code, this in callSos() will be MessageBot.prototype -- certainly not what you want. So you can also do MessageBot.prototype.callSos.call(this, somenumbervar).
Which approach to take depends on how dynamic you want your objects to be. For example, if you want consumers of MessageBot to be able to "override" callSos() by installing their own method, then you should take the first approach (this.callSos()) as it will look up callSos in the object's inheritance chain. This process will only reach the method you've installed on the prototype if the method hasn't been overridden. IMO this is the approach you should take unless you have a very good reason not to.
See this example, which demonstrates how the two approaches differ regarding overriding, while also showing that both work with regards to passing the correct this value (since both methods can retrieve the expected value from this.data):
function ClassA(data) {
this.data = data;
}
ClassA.prototype.foo = function () {
console.log("this.bar() returned: " + this.bar());
console.log("ClassA.prototype.bar.call(this) returned: " + ClassA.prototype.bar.call(this));
};
ClassA.prototype.bar = function () {
return 'in the ClassA prototype, our data is ' + this.data;
};
console.log('--obj1-- (no override)');
var obj1 = new ClassA(3.14);
obj1.foo();
console.log('--obj2-- (override)');
var obj2 = new ClassA(42);
obj2.bar = function () {
return 'in an overriding method, our data is ' + this.data;
};
obj2.foo();
What's the point in setting module.exports to a var vs. just exposing it as plain module.exports? Here are 2 ways possible to set it to a variable and then last just setting it to plain old module.exports. I'm trying to understand the use cases for doing it the various ways and also if the first example makes any sense to set it to an object when I'm doing that sort of thing already in my last example.
var board = module.exports = {
doSomething: doSomething()
};
board.initialize = function(){
...
}
doSomethingElse = function(){
}
or
var board = module.exports = function(){
initialize();
}
function initialize(){
...
}
board.doSomethingElse(){
}
or
module.exports = {
doSomething: doSomething()
};
function doSomething(){
...
};
Seems like there are many ways to do the same kind of things but trying to make sense of good patterns and when.
The difference between the first way and second way is that in the first you are exporting an object whereas in the second you're exporting a function. I generally export as a function if I need to inject some dependency into whatever I'm working with.
As for whether or not to assign module.exports to a variable, there is no practical difference between doing it and not doing it. I generally don't as I like to keep it at the bottom of my module as to highlight exactly what is being exported, but you can do it either way. The important thing is to just do it the same way throughout your application.
I would like to know how can I import an external library to nodejs.
For example I would like to have phanotmjs library (I know that arelady exist an npm to get phantomjs, but is only an example).
I think that a way was to get the source file of library and include it into a module like that:
module.exports = function (name, cb) {
//source code of library
});
But I think it is a wrong way of doing it.
How can I include an external library to nodejs project to use it inside the project with its functionality?
Thanks
Without exporting, a no elegant way is to copy past the entire library, in the bottom of your node file. nasty you may already thought about it. there is also a bad thing about that. you will not be able to reuse it in all different files.
The other way is to export the files along your workflow every time you need a function. And i think this is ok.
Otherwise to answer that, you can write the export this way:
module.exports = {
removeElementFromArray_Mutate,
hasClass,
hasClass_ONEtest,
removeClassFromAll,
addClass,
removeClass
};
you can do that with node. all of those are normal function declared this way:
function removeClassFromAll(DOMobject, classes){
for(let i = 0; i < DOMobject.length; i++){
removeClass(DOMobject[i], classes);
}
}
function hasClass_ONEtest(DOMElement, classe) {
let allClasses = DOMElement.className.split(/\s+/);
for(let i = 0; i < allClasses.length; i++){
if(allClasses[i].trim() === classe){
return true;
}
}
return false;
}
function hasClass(DOMElement, classes) {
if (typeof classes === 'string') {
return hasClass_ONEtest(DOMElement, classes);
} else { // multiple classes as array
for (let i = 0; i < classes.length; i++) {
if (!hasClass_ONEtest(DOMElement, classes[i])) {
return false;
}
}
return true;
}
}
this way you can write a quick script that parse all the file, and take out the definitions of the functions, if you can't do it manually. You can use regex, to speed up that. you need two patterns. the first for function name( and the second for name = function(. Hope that was helpful!
the question was more about if there is a way included with nodejs. There is none at the moment. it may be in the future. You may also see this How do I include a JavaScript file in another JavaScript file?. It may not help though.
When one requires a module on nodejs, the content of module.exports is returned. So, one can return a function (as you do on your example) or an object, as in
in module.js:
module.exports={
func:function(){ return true; },
val:10,
...
}
So that, in the requiring file, you can:
var m=require('module');
assert(m.func()===true);
assert(10===m.val);
This is explained in the nodejs documentation under Modules
So if you have an external JS library that exposes three functions: a, b, and c, you might wrap them as:
module.exports={
exportedA:lib.a,
exportedB:lib.b,
exportedC:lib.c
};
lib.a=function(){ ... };
lib.b=function(){ ... };
lib.c=function(){ ... };
I know that I can set module.exports to either an object or a function
(and in some cases a function that will return an object).
I am also aware of the differences and ways to use exports vs. module.exports so no need to comment on that.
I also understand that whatever is returned is cached and will be returned on any consecutive call to require. So that if I choose to return a function and not an object then possibly this implies that on every require It is necessary to actually run this function.
I was wondering is there any defacto standard on which of those two should be used. Or if there is no such standard - what considerations would apply when deciding if my module should return an object, a function or anything more complicated...
The module I intend to write is expected to be used as part of an express application if it matters (maybe there is a "local defacto standard" for express/connect modules).
If the require'd code is standalone, and does not need access to any objects from the parent code, I export an object.
edit - the above is my preferred way to do it. I do the below only when I need to pass stuff into the module, like configuration data, or my database object. I haven't found a more elegant way to give the module access to variables that are in the parents' scope.
So to pass an object from parent into module I use a function:
//parent.js
var config = { DBname:'bar' };
var child = require('./child.js')(config);
//child.js
module.exports = function(cfg){
var innerchild = {};
innerchild.blah = function(){
console.log(cfg.DBname); // this is out of scope unless you pass it in
}
return innerchild;
};
"so that if I choose to return a function and not an object then
possibly this implies that on every require It is necessary to
actually run this function."
It does not matter whether you return an individual function or an object. In neither cases a function (or functions) are ran. unless you explicitly do so.
For instance, consider the a module hello.js:
exports = function () { return 'Hello'; };
You can use require to get that function:
var hello = require('hello');
If you want to run that function, you need to invoke it explicitly as follows:
var hello = require('hello')();
You wrote you want to make sure your function is executed exactly once. Intuitively this could lead you to writing your hello.js as follows:
var hello = function () { return 'Hello'; };
exports = hello();
In which case you could just store result from hello via require:
var hello = require('hello');
However: if you do that the export system may cache your module. In such cases, you do not get fresh result from hello, but instead, a cached value. This may or may not be what you want. If you want to make sure a function is invoked every time it is required, you need to export a function and call it after require.
I can't really get a grip on what is considered to be good and bad practice when writing a module for in node.js. Some modules seem to use a lot of exports, while other use just one, etc.
Example:
var self;
var mymodule = function() {
self = this;
this.value1 = something;
this.value2 = somethingElse;
};
module.exports.init = function() {
return new mymodule();
};
mymodule.prototype.functionalityType1 = {
someFunction: function(callback) {
var a = self.value1;
anotherfunction(a, callback);
},
};
mymodule.prototype.functionalityType2 = {
someFunction: function(callback) {
var a = self.value2;
anotherfunction(a, callback);
},
};
var anotherfunction = function(v, callback) {
// do stuff with v
callback(result);
};
Each of the prototypes would contain more than one function obviously.
Would something like this be considered good practice?
It really depends on what sort of module you are writing. Exporting multiple functions works well for utility modules which have multiple methods but little to no internal state to manage. Think something like the fs (file system) module. There are a number of file system methods, but they all pretty much stand alone and there is no shared state.
If you're building a stateful module with multiple methods which operate on state then you should probably just export a constructor and allow the client to create an instance of that object that they can manage. An example of this is the http module which allows you to create a server, and that server has methods which affect its internal state.
If you need to have more than one instance of an object from a module then you really don't have much choice but to export a function which returns an instance of the object.
It's not all that different from frameworks like .NET where you have file system (System.IO) classes which have static methods for standalone operations like verifying a directory exists, or reading the contents of a file and then they have instance classes for classes which maintain state.