Dynamic method creation with javascript/nodejs - javascript

I'm trying to create a nodejs module that will have an api like this
**program.js**
var module = require('module');
var products = module('car', 'pc'); // convert string arguments to methods
// now use them
products.car.find('BMW', function(err, results){
// results
})
products.pc.find('HP', function(err, results){
// results
})
>
**module.js**
function module(methods){
// convert string arguments into methods attach to this function
// and return
}
module.find = function(query){
// return results
};
module.exports = module;
I know this is possible because this module is doing the exact same thing.
I have tried to study the source but there is just to much going so was not able to determine how its doing this.

Something like this perhaps? Kinda hard to answer without additionnal details:
function Collection(type) {
this.type = type;
}
Collection.prototype = {
constructor: Collection,
find: function (item, callback) {
//code to find
}
};
function collectionFactory() {
var collections = {},
i = 0,
len = arguments.length,
type;
for (; i < len; i++) {
collections[type = arguments[i]] = new Collection(type);
}
return collections;
}
module.exports = collectionFactory;

Not sure what do you want to do but remember you can have dynamic property name of an object using [] notation like ...
var MyModule = function(param1, param2) {
this.funcTemplate = function() {
console.log('Hi ');
};
this[param1] = this.funcTemplate;
this[param2] = this.funcTemplate;
};
var dynamic = new myModule('what', 'ever');

Related

Function type in javascript

I want to create my own signal emitter or callback storage, call it whatever you want.
Here is what I come up so far:
var DetonationCallback = function detonationCallback() {
detonationCallback.callbacks = [];
detonationCallback.add = function(callback) {
detonationCallback.callbacks.push(callback);
};
for(var i = 0; i < detonationCallback.callbacks.length; ++i) {
callback[i](arguments);
}
};
Basically I have two problems now which I can not tackle. The first one is how can I move
detonationCallback.callbacks = [];
detonationCallback.add = function(callback) {
detonationCallback.callbacks.push(callback);
};
outside of the function? And another question is how can I pass all the arguments which were passed into the detonationCallback just in the same order into callback[i]?
Will be grateful for any answer.
Additional info: when done with the implementation of the type I would like to use it as follows:
var callback = new DetonationCallback();
function f1() {
}
function f2(firstArg, secondArg) {
}
callback.add(f1);
callback.add(f2);
callback();
First, make detonationCallback an Object
var detonationCallbacks = {};
detonationCallbacks.callbacks = [];
detonationCallback.clear = function() {
detonationCallback.callbacks = [];
}
detonationCallback.add = function(callback) {
detonationCallback.callbacks.push(callback);
};
Second, make your detonate a function in detonationCallback
detonationCallback.detonate = function() {
for(var i = 0; i < detonationCallback.callbacks.length; ++i) {
this.callback[i](arguments);
}
};
If you want/need to use new, just create an object prototype for this
I'm not sure why you wan't to move the add function outside but how about using a class instead?
Also note the use of .apply() to send several arguments with an array.
class DetonationCallback {
constructor() {
this.callbacks = [];
}
add(callback) {
this.callbacks.push(callback);
}
call(args) {
this.callbacks.forEach(function(callback) {
callback.apply(this, args);
});
}
}
var callback = function(arg1, arg2) {
console.log(arg1, arg2);
}
var callback2 = function(arg1) {
console.log(arg1);
}
var handler = new DetonationCallback();
handler.add(callback);
handler.add(callback2);
handler.call(['arg1', 'arg2']);
No need to write this yourself:
When using node you can use the built in EventEmitter lib.
https://nodejs.org/api/events.html
There is also a port for the Browser
https://github.com/Olical/EventEmitter

Extend the properties returned by a function?

I'm a JS beginner. I have defined a function on my Backbone model as follows.
myFunction: function () {
return {
firstAttr: this.model.get('value-attribute')
};
}
It is available to me as this.myFunction.
From somewhere else in the code, I want to extend this.myFunction to return another attribute. In other words, I'd like it to return a dict with two attributes: { firstAttr: 'something', secondAttr: true }.
How can I do this?
I've tried:
this.myFunction().secondAttr = true;
but I know that's the wrong thing to do.
Assuming your model prototype looks like
var MyModel = Backbone.Model.extend({
myFunction: function () {
return {
// I assume you work directly on a model
// the principle would be the same with a wrapper object
firstAttr: this.get('value-attribute')
};
}
});
you can either mask your method on a model by model basis like this:
var m = new MyModel({'value-attribute': 'attr, the first'});
console.log(m.myFunction());
m.myFunction = function () {
var res = MyModel.prototype.myFunction.call(this);
res.secondAttr = true;
return res;
};
console.log(m.myFunction());
See http://jsfiddle.net/V8zt2/ for a demo
Or dynamically modify your prototype to alter all instances :
var f = MyModel.prototype.myFunction;
MyModel.prototype.myFunction = function () {
var res = f.call(this);
res.secondAttr = true;
return res;
};
var m = new MyModel({'value-attribute': 'attr, the first'});
console.log(m.myFunction());
http://jsfiddle.net/V8zt2/1/
How about modifying your myFunction to :
myFunction : function () {
var i,
obj = {};
for (i=0; i< arguments.length;i++){
obj['attribute'+(i+1)] = this.model.get(arguments[i]);
}
return obj;
}
This way you can send keys of model, that you want to be in the returned object as arguments to myFunction.

Formatting of a JavaScript function.function()

I have a set of functions that manage CRUD operations on a database.
I am trying to have a top level function that houses the add, update, delete, etc. functions to keep it clean and organized.
I often see Javascript SDKs that look like users.add(param, param) where I am envisioning that it looks something like:
users = function(){
add = function(param,param) {
// do function
}
}
What is the proper way to to do this?
A simple way to do it would be to construct it as an object:
var users = {
add: function(param, param) {
//do function
},
edit: function(param, param) {
//do another function
}
//etc
};
users is usually an object literal, like so:
users = {
add:function(...) {...}
}
Alternatively, it could be an instanciated object (unlikely in this particular case):
function Users() {};
Users.prototype.add = function(...) {...};
users = new Users();
users.add(...);
You can do something like this:
var Users = {
add: function(a,b) {...},
remove: function(a) {...},
};
then call:
Users.add(a, b);
or:
var Users = function(options) { this.init(options); };
// Add a static method
Users.add = function(a,b) {...};
// Also add a prototype method
Users.prototype.remove = function(a) {...};
then do this:
var user = User.add(a, b);
or
var user = new User(user_id);
user.remove();
var users = {
add: function(params) {
// do stuff
},
// more functions
};
Maybe this could be helpful:
var User = function(name){
this.name = name;
this.address = "";
this.setAddress = function(address){
this.address = address;
}
this.toString = function(){
alert("Name: "+this.name+" | Address: "+this.address);
}
}
var a = new User("John");
a.setAddress("street abc");
a.toString();
and to manage a list of users:
var Users = function(){
this.users = new Array();
this.add = function(name, address){
var usr = new User(name);
usr.setAddress(address);
this.users.push(usr);
}
this.listUsers = function(){
for(var x = 0; x < this.users.length; x++){
this.users[x].toString();
}
}
}
var list = new Users();
list.add("Mickey", "disney Street");
list.add("Tom", "street");
list.listUsers();
working example: http://jsfiddle.net/N9b5c/

Javascript module pattern, nested functions, and sub modules

I am trying to wrap my head around javascript modules, but I'm unsure how to split up a module into further sub modules. I have read that nested functions are not really a great idea, due to performance, so how do I break up a function in a module? For example, lets say I have the following module:
var Editor = {};
Editor.build = (function () {
var x = 100;
return {
bigFunction: function () {
// This is where I need to define a couple smaller functions
// should I create a new module for bigFunction? If so, should it be nested in Editor.build somehow?
}
};
})();
bigFunction is only related to Editor.build. Should I attach the smaller functions that make up bigFunction to the prototype bigFunction object? I'm not even sure if that would make sense.
var Editor = {};
Editor.build = (function () {
var x = 100;
return {
bigFunction: function () {
bigFunction.smallFunction();
bigFunction.prototype.smallFunction = function(){ /*do something */ };
// not sure if this even makes sense
}
};
})();
Can someone please throw me in the right direction here? There is so much misleading information online, and would just like a definite guide on how to deal with this sort of modularization.
Thank you.
Here is a snippet I use to make names for an input:
var dynamicCounter = 0;
//custom dropdown names
var createContainerNames = function () {
function Names() {
this.id = "Tasks_" + dynamicCounter + "__ContainerId";
this.name = "Tasks[" + dynamicCounter + "].ContainerId";
this.parent = "task" + dynamicCounter + "Container";
}
Names.prototype = { constructor: Names };
return function () { return new Names(); };
} ();
And then I use it:
var createdNames = createContainerNames();
var createdId = createdNames.id;
dynamicCounter++;
var differentNames = createContainerNames();
var differentId = differentNames.id;
Another approach would be to do this:
var NameModule = function(){
//"private" namemodule variables
var priv1 = "Hello";
//"private namemodule methods
function privMethod1(){
//TODO: implement
}
//"public namemodule variables
var pub1 = "Welcome";
//"public" namemodule methods
function PubMethod(){
//TODO: pub
}
return {
pub1 : pub1,
PubMethod: PubMethod
};
and then to use it
var myPubMethod = new NameModule();
myPubMethod.PubMethod();
var pubVar = myPubMethod.pub1;
EDIT
You could also take this approach:
var mod = function(){
this.modArray = [];
};
mod.prototype = {
//private variables
modId: null,
//public method
AddToArray: function (obj) {
this.modArray.push(obj);
}
}

How can I create a javascript class and access an internal collection using and index/name lookup?

I currently have this:
function SystemCollection () {
this.systems = [];
this.getSystem = function (id) {
for(var s in this.systems) {
if(s.num == id)
return s;
};
return null;
};
this.add = function (system) {
this.systems.push(system);
};
this.count = systems.length;
};
In C#, I'd do something like this:
class SystemCollection {
private List<System> _foo = new List<System>();
public System this[int index]
{
get { _foo[index]; }
}
public System this[string name]
{
get { return _foo.Where( x => x.Name == name).SingleOrDefault(); }
}
}
I don't think you can override the this[] operator in javascript. But what you could do is this. I am assuming system has a property called name
this.add = function(system){
this[system.name] = system;
}
then you can use the collection like this
collection[systemName];
Should do the trick, I hope. If this is not sufficient, then you can augment the value stored under the system name by wrapping it in an object or something like that.
Seems that you are trying to do a sort of key/value pair (systemId / systemName) collection.
The systems array should be private, handled internally only by the add and get methods.
Also since it is an array, you shouldn't use the for...in statement, a normal for loop it's enough, I think something like this:
API tests:
var test = new SystemCollection();
test.add(1, "System One");
test.add(2, "System Two");
test.count(); // 2
test.getSystemByName("System Two"); // Object id=2 name=System Two
test.getSystemById(1); // Object id=1 name=System One
Implementation:
function SystemCollection () {
var systems = []; // private array
// generic function to search by a property name
function getSystem (value, propName) {
var i, s;
for(i = 0; i < systems.length; i++) {
s = systems[i];
if(s[propName] == value) {
return s;
}
}
// will return undefined if this point is reached
}
this.getSystemByName = function (name) {
return getSystem(name, "name");
};
this.getSystemById = function (id) {
return getSystem(id, "id");
};
this.add = function (systemId, systemName) {
systems.push({id: systemId, name: systemName});
};
this.count = function () {
return systems.length;
};
}
I get the feeling that this C# like list will suit your purposes.
Code
function List() {
this.count = 0;
this.add = function(item) {
this[this.count] = item;
this.count++;
}
this.remove = function(index) {
delete this[index];
this.count--;
}
}
Example
var list = new List();
list.add(1);
alert(list.count);
list.add(2);
alert(list.count);
alert(list[1]);

Categories

Resources