Reputation: 2549
Right now I have about 3 seperate javascript "classes". I call them like this;
ajax(parameters).success().error()
getElement('selector').height(400).width(400).remove();
customAlert({object with arguments});
This not only feels like random function calling, but will be likely to give me some naming issues.
Then I thought: How does jQuery
do it?
Well, I have no idea. I've tried googling the subject but so far I haven't found any results of how to make this happen. Only results of how to add prototypes and such...
The basic idea of my classes is like this:
var getElement = function(selector){
if(!(this instanceof getElement))
{
return new getElement(selector);
}
//Do element getting
return this;
};
getElement.prototype = {
name: function,
name: function,
//etc.
};
Now, this is kind of working perfectly fine, but I'd like to "prefix" and scope my functions within a wrapper class. I want to call my functions like this:
wrap.getElement(selector);
wrap.ajax(parameters).success().error();
wrap.customAlert({object with arguments});
However, whenever I try it, I bump into at least one kind of error or issue, like;
this
scope within my classesprototype
functions to my classesnew object()
because the scope isn't right anymoreAlso, if at all possible I would like to not re-initialize the wrapper class every time. (seems wildly inefficient, right?)
So I'd want 1 instance of the wrapper class, while the classes within it get their new instances and just do their thing. Is this even possible or am I just dreaming here?
This is the way I've tried it so far;
//It would probably be easier to use an object here, but I want it to
//default to wrap.getElement(selector) when it's just wrap(selector),
//without re-instantiating the old class
var wrap = function(selector){
//Check if docready and such here
}
wrap.prototype.getElement = function(){
// the getElement class here
}
//This is where it starts going wrong. I can't seem to re-add the prototypes
//back to the getElement class this way.
wrap.getElement.prototype = {
name:function,
name:function,
//etc
}
//I can call wrap().getElement(); now, but not the prototypes of
getElement().
//Also, I still have wrap() while I'd want wrap.getElement.
Then I "solved" the issue of having to do wrap()
by putting it into a variable first.
var test = new wrap();
test.getElement(selector); // works and only inits once!
//However, I did have to remove the 'new instance' from my getElement()
I have also tried it this way, but this just gave me errors on top of errors of which I didn't really know why;
(function(wrap) {
console.log("init")
this.getElement = function() {
return "test";
};
})(wrap);
// Gives me "wrap is undefined" etc.
And last but not least, I have tried it this way;
var wrap = new function() {
return this;
};
wrap.getElement = function(){};
//This works perfectly fine
wrap.getElement.prototype.css = function(){};
//This will cause "getElement.css is not a function"
So yeah, I'm kind of stuck here. There are many ways to get past this in ES6, I've found. I am however not willing to move to ES6 yet (Because I don't use anything that still needs an interpreter). So it has to be ES5.
Upvotes: 1
Views: 1007
Reputation: 5671
The easiest way to wrap your modules in a namespace and keep the classes intact is to use the "Revealing module pattern".
It uses an immediately invoked function expression (IIFE) to set up all the functions with a private scope and then returns just the functions in a new object (which works as a namespace for your module)
var wrap = (function() {
function getElement() {...}
function moreFunctions() {...}
function etcFuncitons() {...}
return {
getElement: getElement,
moreFunctions: moreFunctions,
etcFuncitons: etcFuncitons
};
})();
To answer your second question
I would like to be able to call wrap() by itself as well. I want it to forward automatically to getElement(). Is this hard to do? Is this possible with this construction? Because this looks very easy to maintain and I'd love to keep it like your answer. - Right now it will reply wrap() is not a function
I haven't tested this but you should be able to attach the functions directly to a returned wrapper function. This should avoid the issue of shared this
by adding them to the prototype
var wrap = (function() {
function getElement() {...}
function moreFunctions() {...}
function etcFuncitons() {...}
function wrap(selector) {
return new getElement(selector);
}
wrap.getElement = getElement;
wrap.moreFunctions = moreFunctions;
wrap.etcFuncitons = etcFuncitons;
return wrap;
};
})();
This works because everything is an object in javascript, even functions haha
Upvotes: 1