jS OOP nested functions - javascript

Ok this may be a noobolicious question as im new to OOP.
Im attempting to build something of a JS Object Library and was wondering if I could do it using nested functions??
var object = new function() {
this.action1 = function () {
this.dostuff1 = function () {
return "dostuff1";
};
this.dostuff2 = function () {
return "dostuff2";
};
};
I am having trouble accessing the third level functions. Can I nest like this?
this.action2 = function () {
return "action2";
};
alert(object.action1.dostuff2());

While Eberlin's answer is perfectly correct I'd suggest you to create a nested object which in turn again exposes functions rather than nesting functions itself. Otherwise this might become a maintainability nightmare.
Basically you could create
var Child = function(){
//constructor
};
Child.prototype.doStuff2 = function(){
return "dostuff2";
};
var Root = function(obj){
//constructor
this.child = obj;
};
Root.prototype.action1 = function(){
return "doStuff1";
};
//usage
var myRoot = new Root(new Child());
myRoot.action1();
myRoot.child.action2();
Here's a live example: http://jsbin.com/ijotup/edit#javascript,live

See below for some code cleanup:
var o = (new function () { // changed 'object' to 'o'
this.action1 = (function () { // added parentheses, not required.
this.dostuff1 = (function () { // does not return anything.
return "dostuff1"; // and is also not the proper way to organize
}); // ** look at the javascript prototype
return this; // now it does
}); // missing closing bracket
this.dostuff2 = (function () {
return "dostuff2";
});
});
alert(o.action1().dostuff2()); // action1 is a function, not a variable.
Hope this helps. Also, here's a brief tutorial on the javascript prototype.

Related

Create object of namespace Javascript singleton class

I am new to IIFE and trying to implement namespace in JavaScript on a Siungleton JavaScript class:
I have a JavaScript class (say main class):
var myIIFE = (function () {
var x = null;
//constructor function
var myIIFE = function() {
var a = new IIFE.InsideIIFE(); //says not a constructor
}
myIIFE.prototype = {
//some methods
}
function createIstance() {
return new myIIFE();
}
return {
getInstance: function() {
if (!this.instance) {
this.instance = createInstance();
}
return this.instance;
}
};
})();
Then I have another JavaScript namespaced class:
myIIFE.InsideIIFE = (function() {
var inside = function() {}
inside.prototype = { //some methods }
return inside;
});
I want to create an object of myIIFE.InsideIIFE in myIIFE, and this is throwing me an error:
myIIFE.InsideIIFE is not a constructor
Am I doing something wrong? Or if this is a correct approach then what changes I should make.
I tried using new this.InsideIIFE() and just InsideIIFE, but non of them worked.
edit:
From my analysis, I understand that myIIFE (the parent) is an object as it return an object at:
return {
getInstance: function() {
//method body
}
}
There are many issues with this code, let's try to run it in our heads, from the start:
var myIIFE = (function () {
....
})();
This results in myIIFE being an object, to be precise, this object:
{
getInstance: function() {
if (!this.instance) {
this.instance = createInstance();
}
return this.instance;
}
}
So, then I assume, you do
myIIFE.getInstance()
Which tries to return new myIIFE();
It runs into myIIFE() and tries to do this:
new IIFE.InsideIIFE();
I assume you meant to write
new myIIFE.InsideIIFE();
because IIFE is not defined it anywhere in the code you provided.
Let's see what is myIIFE.insideIIFE
var myIIFE.InsideIIFE = (function() {
var inside = function() {}
inside.prototype = { //some methods }
return inside;
});
First of all you start with var, which is wrong, because myIIFE is already defined and you are just adding a new property to it. so it should be simply
myIIFE.InsideIIFE = (function() {
var inside = function() {}
inside.prototype = { //some methods }
return inside;
});
and it should work.
In general, it seems by your code, like you have not grasped the whole "constructor function" concept very well. I would suggest you take look at the following links, they should help.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript

Javascript namespacing and OO organization

I have my javascript code as follow:
$(document).ready(function () {
//call of global functions
globalFunction1();
globalFunction2(); //create a new object inside
globalFunction3();
}
function globalFunction1() {
// do something directly with jquery selectors
var testObj1 = new object1($('#tree')); // this is called later in the function
testObj.doSomething();
}
function globalFunction2() {
// do other things
}
function globalFunction3() {
// do something directly with jquery selectors
}
//creating an object in js
var object1 = (function () {
var tree;
function object1($tree) {
tree = $tree;
});
}
object1.prototype.doSomething = function () {
.....
};
return fancyStructure;
})();
Normally I have more global functions and if possible I always try to create objects using the new keyword (as in Java or C#)
Now, I am asked to provide namespacing in order to avoid function conflict problems. Thing is I am not sure how to achieve that giving my current code and knowing that I need to keep the code Object Oriented.
Hence, I am wondering if there is a way to add some namespacing effisciently. Any suggestion will do as long as it is along the lines of adding a namespace.
Just put your functions into an Object:
var mynamespace = {
globalFunction1 : function() {
// do something directly with jquery selectors
var testObj1 = new object1($('#tree')); // this is called later in the function
testObj.doSomething();
},
globalFunction2 : function() {
// do other things
},
globalFunction3 : function() {
// do something directly with jquery selectors
}
}
and call the functions with
mynamespace.globalFunction1();
Or you could just define your namespace
mynamespace = {};
And later add the the functions with
mynamespace.globalFunction1 = function() {
//do something
};
Use objects as containers for your functions. This is the standard approach of code structuring in JS.
var namespace1 = {
func1: function() {},
func2: function() {},
}
var namespace2 = {
func1: function() {},
func2: function() {},
}
namespace1.func2();
You can store your OOP code in this namespaces:
var namespace3 = {
someObj: function() {},
create: function() { return new this.someObj(); },
}
namespace3.someObj.prototype = {
count: 15,
someFunc() {}
}
And you can easily extend them:
namespace3.anotherObj = function () {}
Edit
Regarding your example:
var fancyStructureWrapped = (function () {
var tree;
function fancyStructure($tree) {
tree = $tree;
});
fancyStructure.prototype.doSomething = function () {
.....
};
return fancyStructure;
})();
// add it to some namespace
someNamespace.fancyStructure = fancyStructureWrapped;
//create an instance
var fs = new someNamespace.fancyStructure();
//and use it
fs.doSomething();
If you're looking for a general approach to managing a growing JavaScript codebase, check out RequireJS and/or Browserify. Both are libraries that allow dividing your code up into modular bits (ie. AMD or CommonJS modules) and then referencing/importing between them. They include tooling for bundling these files into a single JS file when it's time to deploy a production build too.

Simple Example of Javascript Inheritance?

I've searched on SO and elsewhere for a simple example of inheritance and can't find one. Examples I've seen are obscure, complex, or just make me uncomfortable. I have several service functions that all share some functionality, from what I would call a baseservice:
function baseservice() {
var loadAnimate = function () {
$('#ajax-spinner').show();
};
var loadComplete = function () {
$('#ajax-spinner').hide();
};
var apiEndpoint = function() {
return "http://api.com/api/";
};
};
I have other services now that have this functionality:
var documentservice = function() {
// repeated code
var loadAnimate = function () {
$('#ajax-spinner').show();
};
var loadComplete = function () {
$('#ajax-spinner').hide();
};
var apiEndpoint = "http://api.com/api/";
var sendRequest = function (payload, callback) {
loadAnimate();
// do stuff with apiEndpoint
// call loadComplete on promise
};
How can I provide documentservice with access to those items in baseservice?
Since Javascript is a prototypical language, it doesn't have the same sort of class inheritance that a language like, say, Java has. If you want a very simple instance of inheritance, you could try something like:
function baseservice() {
this.loadAnimate = function () {
$('#ajax-spinner').show();
};
this.loadComplete = function () {
$('#ajax-spinner').hide();
};
this.apiEndpoint = function() {
return "http://api.com/api/";
};
};
var documentservice = new baseservice();
documentservice.sendRequest() = function() { /* ... */ }
Then, documentservice has all of baseservice's members (note the this. in baseservice's function declaration instead of var).
If you don't want to have to use the new keyword, you can create a function extend either adds a field pointing to baseservice (document.baseservice = baseservice) or does a deep (recursive) copy, then adds documentservice.sendRequest.
Of course, folks have already worked on this with things like ded/klass.

Javascript Revealing Module pattern - exposing initialization variables after function has returned

I’ve been using the Javascript Revealing Module pattern a lot and I like the clear separation it gives between the public interface and the internals. However I keep running into a situation which makes me wonder if my overall usage pattern is correct, or if I should use some variant of the pattern.
The problem is when something passed into the init function of a module and stored privately for internal use also needs to be publicly exposed, either in a Knockout binding expression or some other module. The return statement of the module executes immediately and sometime later the init function is called, typically being passed some dynamic parameters such as Ajax URLs or raw JSON rendered in a script block within a Razor view. Because the module's return statement just returns a copy of the private variable rather than a reference, my setting that private variable in the init function can’t change what has already been returned.
var productsModule = function() {
var urls;
var init = function(ajaxUrls) {
urls = ajaxUrls;
};
return {
init: init,
urls: urls,
getUrls: function() { return urls; }
};
}();
var customersModule = function() {
var doSomethingWithProductsModule = function() {
alert(productsModule.urls); // undefined
alert(productsModule.getUrls()); // object
} ;
return {
doSomethingWithProductsModule: doSomethingWithProductsModule
};
}();
var urls = {
getProduct: '/Product/'
};
productsModule.init(urls);
customersModule.doSomethingWithProductsModule();
My workaround is just to wrap objects such as “urls” in a function and then access them via productsModule.getUrls(). However that becomes very messy, especially if the variable is a Knockout observable which is itself a function, and hence to evaluate it I need to use double brackets like productsModule.getMyObservable()().
Is there a nicer way to get at the up-to-date internal values using something which at least approximates the revealing module pattern?
Basic types are passed by value while objects are passed by reference; you could exploit this so that instead over overwriting urls in productsModule you just update it. This way the reference returned in the initial module invocation remains up to date. I've updated your code to show what I mean.
var productsModule = function() {
var urls = {};
var init = function(ajaxUrls) {
// Merge properties into the original object instead; more robust approach
// may be needed
for ( name in ajaxUrls ) {
if (ajaxUrls.hasOwnProperty(name)) {
urls[name] = ajaxUrls[name];
}
}
};
return {
init: init,
urls: urls,
getUrls: function() { return urls; }
};
}();
var customersModule = function() {
var doSomethingWithProductsModule = function() {
alert(productsModule.urls); // undefined
alert(productsModule.getUrls()); // object
} ;
return {
doSomethingWithProductsModule: doSomethingWithProductsModule
};
}();
var urls = {
getProduct: '/Product/'
};
productsModule.init(urls);
customersModule.doSomethingWithProductsModule();
Although I don't completely like the idea of having to iterate through all the possible levels of my objects to merge them like that, El Yobo's answer got me thinking about making the result of the module function itself a local variable whose properties I could update.
var productsModule = function() {
var urls;
var init = function(ajaxUrls) {
urls = ajaxUrls;
result.urls = urls;
};
var result = {
init: init,
urls: urls
};
return result;
}();
// Before init
alert(productsModule.urls); // undefined
var urls = {
getProduct: '/Product/'
};
productsModule.init(urls);
alert(productsModule.urls.getProduct); // /Product/
Why don't you make urls an observable property ?
Look at my example:
http://jsfiddle.net/Razaz/zkXYC/1/
var productsModule = function() {
var urls=ko.observable();
var init = function(ajaxUrls) {
urls(ajaxUrls);
};
return {
init: init,
urls: urls,
getUrls: function() { return urls(); }
};
}();
var customersModule = function() {
var doSomethingWithProductsModule = function() {
alert(productsModule.urls()); // undefined
alert(productsModule.getUrls()); // object
};
return {
doSomethingWithProductsModule: doSomethingWithProductsModule
};
}();
var urls = {
getProduct: '/Product/'
};
productsModule.init(urls);
customersModule.doSomethingWithProductsModule();​
Greetings.

How to structure javascript objects, while not getting 'undefined' is not a function errors?

If I have a javascript class that runs some initialization code, it seems logical to put this code at the top, and any methods at the bottom of the class. The problem is, if the initialization code contains a method call, I get a 'undefined' is not a function error. I imagine because the method is defined after the method call. How do people normally structure javascript classes to avoid this? Do they put all the initialization code at the end of the class? For example:
var class = function() {
this.start();
this.start = function() {
alert('foo');
};
};
var object = new class();
causes an error, while:
var class = function() {
this.start = function() {
alert('foo');
};
this.start();
};
var object = new class();
does not. what would be considered a good structure for a javascript object like this?
Here's what I would do
// create a "namespace"
var com = com || {};
com.domain = com.domain || {};
// add "class" defintion
com.domain.MyClass = function(){
var privateFields = {};
var publicFields = {};
privateFields.myFunction = function(){
// do something
}
publicFields.initialize = function(){
privateFields.myFunction();
}
return publicFields;
}
var myClass = new com.domain.MyClass();
myClass.initialize();
of course, you could just make initialize(); "private" and run it before return publicFields;
var class = function() {
this.start();
};
class.prototype.start = function() {
alert('foo');
};
var object = new class();
now you can mess around with start as much as you want in the constructor. but dont use the keyword class as it is a reserved word.
I like http://ejohn.org/blog/simple-javascript-inheritance/ where I feel much more programing OOP.
var myClass = Class.extend({
init: function () {
this.foo();
},
foo: function () {
alert("foo");
}
});
new myClass();
Consider making start a method on class's prototype. This has the bonus of saving memory since all instances of class can share the same start, instead of creating a new start function for each instance.
var class = function() {
this.start();
};
class.prototype.start = function() {
alert('foo');
};
var object = new class();
I actually work a lot with structures like this:
var foo = function() {
// Actual construction code...
start(); // <-- doesn't make a difference if functions are
privateMethod(); // public or private!
// ---------------------------------
function start() {
// ... whatever ...
};
function privateMethod() {
// ... whatever ...
};
// ---------------------------------
// Add all public methods to the object (if start() was only used internally
// just don't assign it to the object and it's private)
this.start = start;
};

Categories