how to pass variable to Javascript Namespace - javascript

I have created a Javascript namespace like so:
var MyApp = function() {
return {
someFunction : function(x) {}
alert(MyApp.y);
}
}();
This allows me to do this:
MyApp.someFunction(x);
I would like to be able to do the following:
MyApp.y = "test" so that my someFunction can access this variable Y.
Any ideas on how to solve this? I'd like to keep my NS syntax intact so a solution that works with my example code would be nice.

What you described should work. (Except you have a syntax error and an unused argument x.)
var MyApp = function() {
return {
someFunction : function(x) {
alert(MyApp.y);
}
}
}();
MyApp.y = 'test';
MyApp.someFunction() // alerts 'test'
Another approach is to treat your outer function more like a constructor and pass y as a closure:
var MyApp = (function (y) {
return {
y: y,
someFunction: function () {
alert(MyApp.y); // or alert(this.y)
}
}
} ('test'));
MyApp.someFunction(); // alerts 'test'

I would go with something like this:
var MyApp = function() {
var _y = "default value";
return {
someFunction: function(x) {
console.log(_y);
},
setY: function (y) {
_y = y;
}
}
}();
This will mean that it is safe to call MyApp.someFunction() before assigning a value to y. It also means that the contents of the variable is maintained within the namespace's scope, e.g.
console.log(MyApp._y); // undefined
Here would be how to use it:
MyApp.someFunction(); // "default value"
MyApp.setY("new value");
MyApp.someFunction(); // "new value"

Related

JavaScript Self Invoking function properties

Trying to understand JS better, have a couple of clarifications. Lets suppose we have the following method
var customer = function(){
var name = "Contoso";
return {
getName : function(){
return this.name;
},
setName : function(newName){
this.name = newName;
}
}
}();
why is name not visible outside ?, when we log (customer.name) its undefined, however if we remove the self initializing parenthesis on function and change the variable declaration to (this.name) & again when we log the same we are able to see the value. what am i missing in here.
You need to take in consideration that JavaScript doesn't really have native classes. With this said, the way you can create constructors in order to "mimic" a class and be able to use this you need to create something like so:
function fnc (string) {
this.string = string;
}
fnc.prototype.getString = function() {
return this.string;
}
var x = new fnc('bar');
console.log(x.getString()); //bar
This is called the Constructor Pattern.
What you're trying to do is use something called the Module Pattern which works something like so:
var fn = (function() {
var string = 'foo';
return {
getString() {
return string;
}
}
})();
console.log(fn.getString()); //foo
Here is a working example: https://repl.it/FCn7
Also, a good read: https://addyosmani.com/resources/essentialjsdesignpatterns/book/
Edit
Example using getString and setString with the Module Pattern
var fn = (function() {
var string = 'foo';
return {
getString() {
return string;
},
setString(str){
string = str;
}
}
})();
fn.setString('xyz');
console.log(fn.getString()); // xyz
var is creating variable inside function scope which is not available outside as function property. If you want to access properties like customer.name you need to initialize it as this.name as you noticed.
var in this example is like creating private variable which can be modified by functions, but not directly.
SO this will work:
var customer = function(){
var name = "Contoso";
return {
getName : function(){
return name;
},
setName : function(newName){
name = newName;
}
}
}();

UnCaught TypeError - Nested objects in Javascript? Why is this not allowed? Object literal notation works

Playing around with some JS tests and I'm trying to instantiate some nested objects in my v namespace. As you'll see below, ClassA and ClassB work as expected. When I try and nest some objects under another property (myCustomProperty) I start running into issues! Could someone explain?
Below is the original code:
var v = (v) ? v : {};
v.someClassA = (function() {
this.hello = function() {
console.log("Class A Hello!");
}
});
v.someClassB = (function() {
this.hello = function() {
console.log("Class B Hello!");
}
});
// this all works!
var myClassA = new v.someClassA();
var myClassB = new v.someClassB();
v.myCustomProperty = (function() {
function someClassC() {
this.hello = function() {
console.log('C');
}
}
function someClassD() {
this.hello = function() {
console.log('D');
}
}
return {
someClassC: someClassC,
someClassD: someClassD
}
});
// Uncaught TypeError: v.myCustomProperty.someClassC is not a function! Why?
var myClassC = new v.myCustomProperty.someClassC();
var myClassD = new v.myCustomProperty.someClassD();
myClassA.hello();
myClassB.hello();
myClassC.hello();
myClassD.hello();
If I change my declaration of v.myCustomProperty to use object literal notation, then it ALL WORKS! :
v.myCustomProperty = {
someClassC: function() {
this.hello = function() {
console.log('C');
}
},
someClassD: function() {
this.hello = function() {
console.log('D');
}
}
}
I guess my question really is how would I make this work using the notation in my original snippet? Possible? Horrible practice to do it that way?
Thanks!
v.myCustomProperty is a function that returns an object. You have to call the function first:
new (v.myCustomProperty().someClassC)();
// ^^
Otherwise, v.myCustomProperty.someClassC() tries to access the property someClassC of the function, and we all know (hopefully) that functions don't have such a property.
Or maybe you intended to execute the function immediately and assign the object to myCustomProperty?
v.myCustomProperty = (function() {
// ...
}()); // <- call function

Javascript singleton class default value

How can I set a default value in my singleton class. I have this dictionary in my class where the variable name "myVar" is assigned a value of 3. However, running this code below does not return a value of 3, instead it returns undefined.
init = function() {
var var1 = Singleton.myVar;
console.log(var1); // Returns undefined
var1 = 3;
console.log(var1);; // Returns 3
var var2 = Singleton.myVar;
console.log(var2); // Returns undefined
}
Singleton Class:
var Singleton = (function(){
var instantiated;
function init (){
// all singleton code goes here
return {
myVar: 3,
publicWhatever:function(){
alert('whatever')
},
publicProperty:2
}
}
return {
getInstance :function(){
if (!instantiated){
instantiated = init();
}
return instantiated;
}
}
})()
You need to use the getInstance function to get your singleton instance :
var var1 = Singleton.getInstance().myVar;
Note that your factory seems overly complicated. I see the point in using an IIFE (you could define additional private fields or functions) but you could use an IIFE and reduce your singleton factory to
var Singleton = (function(){
return {
myVar: 3,
publicWhatever:function(){
alert('whatever')
},
publicProperty:2
}
})();
Why is your singleton declaration a function at all? Why not just declare the object directly, like so:
var Singleton = {
myVar: 3,
publicWhatever:function(){
alert('whatever')
},
publicProperty:2
};
Why not just do:
var Singleton = function() {
return {
...
myVar: 3,
...
}
})();
Rather than have another layer inside the singleton?

variable in my javascript class is undefined when using an instance of that class

I have declared this javascript class:
var TablixColumns = function(){
this.g = 'wtf';
this.tablixColumns = []; //[];
return {
addTablixColumn: function(tablixColumn){
alert(this.g);
//this.tablixColumns.push(tablixColumn.getTablixColumn());
}
}
};
my problem is that when I try this: alert(this.g) the alert comes out undefined
of course my initial function definition read: this.tablixColumns.push(tablixColumn.getTablixColumn());
but then I get the error that reads something like "No Method push of undefined"
what's weird is I have this class declaration:
var TablixColumn = function(){
columnWidth = '<Width>3.135cm</Width>'; //default width value
return{
setColumnWidth: function(width){
this.columnWidth = '<Width>' + width + 'cm</Width>';
},
getTablixColumn: function(){
return '<TablixColumn>' + this.columnWidth + '</TablixColumn>';
}
}
};
and the TablixColumn class works fine,
and yes, I have declared this.g and this.tablixColumns without the 'this.' part, but it's just refusing to work!
I'm going to kill someone if this doesn't work tonight can someone help me please?
You need to set a reference to the current object (this) outside the nested function expression. Here's how your code should look:
var TablixColumns = function() {
...
var self = this;
return {
addTablixColumn: function(tablixColumn) {
alert(self.g);
}
};
};
You can even set a property to the returned object literal if you want:
// ...
return {
g: 'wtf',
addTablixColumn: function(tablixColumn) {
alert(this.g); // 'wtf'
}
};
// ...
Note that you shouldn't use TablixColumns as a constructor if you're returning from it like this. You're using two idioms here; prototypal inheritance and the module pattern. Are you going to instantiate the constructor with new? If so, then don't return the object literal. Rather, set the methods on the prototype of the function:
var TablixColumns = function() {
this.g = 'wtf';
this.tablixColumns = [];
};
TablixColumns.prototype.addTablixColumn = function addTablixColumn() { ... };
TablixColumns.prototype./* ... */
...
Otherwise, don't use this inside the constructor. Simply make the properties normal variables.
Okay guys so I figured out my problem:
all the references to variables of the current instance should not have been preceded by the this. keyword
so this is how my declaration looks now:
var TablixColumns = function(){
g = 'wtf';
tablixColumns = []; //[];
return {
addTablixColumn: function(tablixColumn){
alert(g);
tablixColumns.push(tablixColumn.getTablixColumn());
}
}
};
Thanks #Bergi for pointing this out

JavaScript Module Pattern - What about using "return this"?

After doing some reading about the Module Pattern, I've seen a few ways of returning the properties which you want to be public.
One of the most common ways is to declare your public properties and methods right inside of the "return" statement, apart from your private properties and methods. A similar way (the "Revealing" pattern) is to provide simply references to the properties and methods which you want to be public. Lastly, a third technique I saw was to create a new object inside your module function, to which you assign your new properties before returning said object. This was an interesting idea, but requires the creation of a new object.
So I was thinking, why not just use this.propertyName to assign your public properties and methods, and finally use return this at the end? This way seems much simpler to me, as you can create private properties and methods with the usual var or function syntax, or use the this.propertyName syntax to declare your public methods.
Here's the method I'm suggesting:
(function() {
var privateMethod = function () {
alert('This is a private method.');
}
this.publicMethod = function () {
alert('This is a public method.');
}
return this;
})();
Are there any pros/cons to using the method above? What about the others?
Your function has no object context, so this references to the global window object in this case. Every property you assign to this automatically pollutes the global namespace.
(function() {
console.log(this == window); // true
this.publicMethod = function () {
alert('This is a public method.');
}
})();
console.log(publicMethod); // function()
You can explicitly pass it an object to tell which context to use.
var MYAPP = {};
(function() {
// 'this' will now refer to 'MYAPP'
this.publicMethod = function () {
alert('This is a public method.');
}
}).call(MYAPP);
console.log(publicMethod); // undefined
console.log(MYAPP.publichMethod); // function()
Which you can write in somewhat other style:
var MYAPP = (function(my) {
var my;
⋮
return my;
})(MYAPP);
And we arrived to an already discussed pattern. For further details, see Dustin's article on Scoping anonymous functions.
I would recommend the style where you add your public properties and methods to an anonymous object that you then return:
var myModule = (function() {
function privateMethod() { ... }
function publicMethod() { ... }
return { publicMethod: publicMethod };
})();
if you want to publish methods, then do something like:
var export = (function() {
var privateMethod = function () {
alert('This is a private method.');
}
var export = {};
export.publicMethod = function () {
alert('This is a public method.');
}
return export;
})();
Another option is to avoid the this reference altogether. Define a function that creates and returns an anonymous object instead.
function makeThing(someAttribute) {
var privateVariable = 42;
function someMethod() {
return privateVariable;
}
return {
"publicMethodName": someMethod,
"getAttribute": function() {
return someAttribute;
}
};
}
var thing = makeThing(99);
thing.publicMethodName();
thing.getAttribute();
Revealing Module patterns:
var m1 = (function(){ return {method: mthod} })();
var m2 = new function Singleton(){ return {method: mthod} };
var m3 = ({}).prototype = {method: method};
var m4 = ({}).prototype = (function(){ ... })();
var m5 = (function(){}).prototype = {} || (function(){ ... })();
var m6 = (function(extendee){
return extendee.prototype = {attr3: 'attr3'};
})({currentAttr1: 1, currentAttr2: 2});
Also, if you need method-chaining:
var m = (function(){}).prototype = (function(){
var thus = m; // this
console.log('m this-------', thus);
function fn(){
console.log('fn', thus);
return thus;
}
function f(){
console.log('f', thus);
return 'poop';
}
return {f: f, fn: fn};
})();
console.log('M:', m, 'm.fn', m.fn(), 'm.fn.f', m.fn().f());
There's also plenty more ways, and you can protagonize your modules as well.

Categories

Resources