Storing different objects in same variable - javascript

I'm trying to figure out how i could store different objects in a certain "namespace".
I have something like this:
app.js
// This is the startup script:
var MyApp = {}
MyApp.ui = {}
MyApp.ui = require('ui/MainWindow');
MyApp.ui = require('ui/SecondWindow');
// Doesn't exist anymore because the 2nd require overwrites the
// first include
MyApp.ui.MainWindow.test;
Then i also have MainWindow.js and SecondWindow.js, which looks like this:
var MainWindow = {
test: "Main"
}
exports.MainWindow = MainWindow;
var SecondWindow = {
test: "Second"
}
exports.SecondWindow = SecondWindow;
The exports.XXXWindow = XXXWindow basically makes that object available.
So in my app.js i try to store the MainWindow object in MyApp.ui. So i can call it like this:
MyApp.ui.MainWindow.test
Then i'd also like to add the SecondWindow object to that. So i can call that in the same way:
MyApp.ui.SecondWindow.test
But the way i have it now causes the second require to overwrite the first one. So it now only points to SecondWindow. What do i have to do so that i can call both objects from MyApp.ui ??

I suggest you to do (I'm sorry if code is not syntactically correct but I use coffeescript and I'm not used anymore to Javascript):
MainWindow.js
var MainWindow = function() {
return {test: 'Main'};
};
module.exports = MainWindow;
SecondWindow.js
var SecondWindow = function() {
return {test: 'Second'};
};
module.exports = SecondWindow;
app.js
var myApp = {
ui: {
MainWindow: require('MainWindow.js'),
SecondWindow: require(SecondWindow.js)
}
};
Now my personal opinion. I prefer to do:
app.js
var MainWindow = require('MainWindow'),
SecondWindow = require('SecondWindow'),
myApp = {
ui: {
MainWindow: new MainWindow(),
SecondWindow: new SecondWindow()
}
};

The second assignment of MyApp.ui will overwrite its old value. However, you could do the following:
function inject(obj_into,obj_from){
for(var x in obj_from)
obj_into[x] = obj_from[x];
}
MyApp.ui = {MainWindow:{},SecondWindow:{}};
inject(MyApp.ui.MainWindow,require('ui/MainWindow'));
inject(MyApp.ui.SecondWindow,require('ui/SecondWindow'));
You first initialize MyApp.ui with empty property objects MainWindow,SecondWindow and fill them with inject.

Related

execution order - new object's function undefined

I've created an app object which contains an empty modules object within it defined in the constructor.
var App = function() {
this.modules = {};
};
The modules object contains references to other objects (modules) that make up the app and contain their logic.
I instantiate the app like this
window.app = new App();
app.createModules();
createModules() fills the modules object with the modules of the app. Then when it is done, it runs initModules() that calls each modules init() function. In this way I hope to be able to control the execution order so that objects dependent on other objects will load correctly. The code for this is as follows:
App.prototype.createModules = function() {
console.log("Creating Modules");
this.modules = {
radio: new Radio(),
visualiser: new Visualiser()
};
this.initModules(this.modules);
}
App.prototype.initModules = function() {
console.log("Initialising modules");
for (var key in this.modules) {
if (this.modules.hasOwnProperty(key)) {
var obj = this.modules[key];
console.log(obj);
console.log(obj.init); //logs 'undefined'
}
}
}
Currently the console log on obj.init is returning undefined, meaning that I can't run the init code for that object. But when the page is finished loading if I call
app.modules.radio.init
It returns the function. I can't seem to figure out why is this happening.
Cheers!
EDIT
Here is the structure of app:
var app = function() {
...
}
window.app = new App();
app.createModules();
function Radio() {
...
}
Radio.prototype.init = function() {
...
}
function Visualiser() {
...
}
Visualiser.prototype.init = function() {
...
}
//Event code
Codepen: https://codepen.io/anon/pen/EvggLZ?editors=0011
Here is the structure of app
Yes, that calls the methods before they are created on the prototypes. Move the
window.app = new App();
app.createModules();
to the bottom of the script and it will work.

How to export and import two different function objects in JavaScript?

I use Jasmine-Node to test Javascript code.
How can one export two different function objects like Confusions1 and Confusions2 so that both are available in the Jasmine-Node test file?
My attempt looks like this:
// confusions.js
var Confusions1 = function() {};
Confusions1.prototype.foo = function(num) {
// keep track of how many times `foo` is called
this.count++;
}
module.exports = Confusions1;
// second function object
var Confusions2 = function() {};
Confusions2.prototype.foo = function() {
var a = 2;
this.bar();
};
Confusions2.prototype.bar = function() {
return this.a;
}
module.exports = Confusions2;
And my Jasmine Test file:
// confusions.spec.js
var Confusion = require('./confusions.js');
describe("chapter 1, common misconception ", function() {
describe("to assume `this` refers to the function itself: ", function() {
var confusion = new Confusion();
// some test code omitted
});
describe("to assume `this` refers to the function's scope", function() {
var confusion = new Confusion();
// test code omitted
});
});
I want it so that Confusions1 and Confusions2 from confusions.js are both usable in the two nested describe blocks within confusions.spec.js
I assume that I have to somehow initialize different objects after requiring the file var Confusion = require('./confusions.js');
Something like var confusion1 = new Confusions1(); var confusion2 = new Confusions2(); But how exactly (without splitting both Objects in two separate files)?
So you want to have a module that behaves like a container of exported values, in another words you want to export two functions:
// foo.js
var Confusion1 = function() {}
var Confusion2 = function() {}
...
exports.Confusion1 = Confusion1
exports.Confusion2 = Confusion2
Wherever you need this module, you could require this stuff like:
// bar.test.js
var confusions = require('path-to-the-foo-file')
console.log(confusions.Confusion1)
console.log(confusions.Confusion2)
Also as it seems you should check how module system that you are using works in general, check this answer: module.exports vs exports in Node.js

JavaScript function prototype calling parent from child

I have a stupid reference problem
I declared a namespace variable called MYAPP
var MYAPP = MYAPP || function() {
this.name = 'My Application';
this.someImportantID = 123;
};
And then I wanted to sperate my code in namespaces/functions and so I did
MYAPP.prototype.homepage = function() {
urls: {
linkOne: '/link/to/some/page/',
linkTwo: '/link/to/some/page/'
},
doSomething: function() {
// ajax call
$getting = $.get(this.urls.linkOne)
// and so on .....
// how can I acces someImportantID ??
}
}
then i use it like this
app = new MYAPP();
app.homepage.doSomething();
but how can I access someImportantID within the function doSomething()
Get rid of this .homepage stuff. Why are you doing that anyway?
This is something of a constructor pattern. Declare your constructor:
var MYAPP = function(URLCollection) {
this._name = 'My Application';
this._someImportantID = 123;
this._URLCollection = URLCollection;
}
Then declare the instance methods:
MYAPP.prototype = {
doSomething: function() {
// ajax call
$getting = $.get(this._URLCollection.linkOne);
// and so on .....
// how can I acces someImportantID ??
}
}
Then declare your instance passing in your collection of links:
var lCollection = { linkOne: 'URL', linkTwo: 'URL' };
var myHomePage = new MYAPP(lCollection);
You can access doSomething from the instance:
myHomePage.doSomething();
You can get to some important ID from the instance also:
myHomePage._someImportantId;
Or from within the instance, by:
this._someImportantId;
This is rough - it should point you in the right direction.
If there are multiple MyApp instances then you can do the following:
//IIFE creating it's own scope, HomePage constructor
// is no longer globally available
;(function(){
var HomePage = function(urls,app){
this.urls=urls;
this.app=app;
}
HomePage.prototype.doSomething=function(){
console.log('urls:',this.urls,'app:',this.app);
}
//assuming window is the global
window.MyApp = function(urls){
this.name='app name';
this.homePage=new HomePage(urls,this);
}
}());
var app = new MyApp(['url one','url two']);
app.homePage.doSomething();
If you only have one app and that app only has one homePage object you can do it the following way as well:
var app = {
name:'app name'
,homePage:{
urls:['url one','url two']
,doSomething:function(){
console.log('urls:',this.urls,'app:',app);
//or
console.log('urls:',app.homePage.urls,'app:',app);
}
}
}
app.homePage.doSomething();
More on constructor functions, prototype and the value of this here.

Right way of writing and loading modules in node.js?

Currently, I write node.js modules like this:
//MyModule.js
function MyModule() {
...somecode
}
MyModule.prototype.someFunc = function() {...}
module.exports = MyModule
However, when I need to use the module, I have to write something like this:
//main.js
var MyModule = require('MyModule');
var myModule = new MyModule();
This seems terribly ugly. Isn't there some way to do something like this
//main.js
var myModule = require('MyModule').new();
Am I doing something wrong?
quick hack for something not ugly
module.js
function MyModule() {
console.dir('constructor');
}
module.exports = MyModule;
app.js
Function.prototype.new = function () {
return new this();
};
var MyModule = require('./module.js').new(); // 'constructor'
If your module consists solely of functions, it may not need to be created as an instance - just define your module as being an object filled with functions. Like so:
var MyModule = {
prepareHtmlContent: function() {
},
autoLoadActionInitiatorFunctions: function() {
}
};
The reason I suggest this is that you've referred to your object as 'MyModule'. If your intent is specifically to use it as a 'Class', and instantiate separate copies of it when they're needed, then you're doing it the correct way.
Here is what I use
(function(module) {
module.myFunction = function() {
}
module.createSomeObj = function() {
return {
foo: 1,
bar: 'bar'
};
}
}(module.exports));
Usage
var myModule = require('./myModule');
myModule.myFunction();
var myObject = myModule.createSomeObj();

Is this a safe way to reference objects in JavaScript?

If I were to define two objects myDataStore and myDrawer something like this:
var myDataStore = function(myObjectRef) {
this.myInternalObject = myObjectRef;
};
var myDrawer = function(myObjRef) {
this.myInternalObject = myObjectRef;
};
And if I were to create an object like so:
[[EDIT - Adjusted Object Creation to Ensure 'this' is being mapped to myObject, not the global window object]]
(function(){
var myObject = window.myObject = function(){
this.dataStore = new myDataStore(this);
this.drawer = new myDrawer(this);
}
})();
Then myObject.dataStore.myInternalObject, and myObject.drawer.myInternalObject, would simply be pointers back to the original 'myObject' - not taking up any additional memory in the browser. Yes?
I am interested in implementing techniques like this - as it makes it easy for objects to communicate with each other.
Nope. this refers to whatever is on the left hand side of the . or if there is no left hand side of the . then it's the global object.
So if you did this:
var MyObj = {
"create": function() {
var myObject = {
dataStore = new myDataStore(this);
drawer = new myDrawer(this);
};
}
};
MyObj.create();
this would be MyObj. If you did this:
var myObject = {
dataStore = new myDataStore(this);
drawer = new myDrawer(this);
};
(not in a function) this would be window (assuming this is in a browser).
Yes, your assumption is correct. myInternalObject will be a reference and not a new object. You can test it like this:
var MyDataStore = function(myObjectRef) {
this.myInternalObject = myObjectRef;
};
var data = {
value: "value"
};
var dataStore = new MyDataStore(data);
data.value = "test";
console.log(dataStore.myInternalObject); // logs { value : "test" } instead of { value: "value" }
No. myObject.dataStore.myInternalObject and myObject.drawer.myInternalObject will both point to the global object (mapped to window in browsers), unless you're inside a function already when you declare myObject. In other words, it will be set to whatever this is in the context in which you declare myObject. It won't be myObject itself.

Categories

Resources