Passing variables between two JavaScript modules not working - javascript

I have two modules within the same namespace, and I want to pass a variable between them. The namespace is called app, and the variable is a - but for some reason my variable a always comes out null when my method is called.
Here is the code:
// module 1
(function() {
app.module1 = (function() {
var a = null;
canvas.addEventListener('mousedown', function(e) {
a = { message: hallo };
app.module2.print();
}, 0);
return {
a: a
};
})();
})();
// module 2
(function() {
app.module2 = (function() {
var print = function() {
console.log(app.module1.a);
}
return {
print: print
};
})();
})();

Check this jsbin
Basically what you can do is to calculate variable each time:
In your module 1:
a: function(){return a;}
Wherever you are using a:
console.log(app.module1.a());

It's because your handler is referring to the local a and not the a property on the module. I suggest you modify the object instead, or you could do this:
// module 1
(function () {
app.module1 = (function () {
var interface = {
a: null
};
canvas.addEventListener('mousedown', function (e) {
//this way, you are modifying the object
interface.a = {
message: hallo
};
app.module2.print();
}, 0);
return interface;
})();
})();

Related

How to preserve javascript "this" context inside singleton pattern?

I have something similar to this:
var a = (function () {
return {
b: 1,
c: function () {
console.log(this.b);
}
};
})();
So,
a.c(); // = 1
But if I do
b = 2;
a.c.apply(this); // = 2
Is it possible to preserve the context of "this" inside "a.c()" without changing (too much) the structure of "a" object? I don't have the control of the function's call, so I'd need a workaround to deal with this inside the object itself.
UPDATE:
To be more specific, this is the structure of my files:
Structure 1 (singleton like pattern):
var a = (function () {
var _instance;
function init() {
return {
b: 1,
c: function () {
console.log(this.b);
}
};
}
return {
getInstance: function () {
if (_instance === undefined) {
_instance = init();
}
return _instance;
}
}
})();
Structure 2:
var b = {
c: 1,
d: function () {
console.log(this.c);
}
};
SOLUTION:
I have implemented a solution based on Mahout's answer, spliting the return statement inside init(), so it remains safe for the object context (and the instance) under any situation.
For singleton pattern:
var a = (function () {
var _instance,
self;
function init() {
return self = {
b: 1,
c: function () {
console.log(self.b);
}
};
}
return {
getInstance: function () {
if (_instance === undefined) {
_instance = init();
}
return _instance;
}
};
})();
For object literal:
var b = (function () {
var self;
return self = {
c: 1,
d: function () {
console.log(self.c);
}
};
})();
So
a.getInstance().c(); // 1
a.getInstance().c.apply(this); // 1
setTimeout(a.getInstance().c, 1); // 1
$.ajax({ complete: a.getInstance().c }); // 1
You can slightly change the way you are returning the object from the anonymous function:
var a = (function () {
var result = {};
result.b = 2;
result.c = function() {
console.log(result.b);
};
return result;
})();
This should have the same effect, however it does remove the use of this.
If you can't afford to change the structure of a this much, then alternately you can (much) more dangerously use:
a.c.apply = function() { // Stops the apply function working on a.c by overriding it
return a.c();
}
If you choose this though you must be wary that anytime a.c.apply is used it will no longer work 'as expected' - it will fix the issue presented here though.
I made this pen to illustrate the differences,I hope it helps:
http://codepen.io/dieggger/pen/BNgjBa?editors=001
var a = (function () {
return { b: 1,
c: function () {
console.log(this.b);
}
};
})();
a.c(); //prints 1
b = 2; // global variable "b" which is being hoisted BTW
// The following will act like this:
//it throws "cannot read property 'apply' from undefined"
//though it prints "1" since the first part invokes the "c" function
//inside of the"a" module which has the console.log
a.c().apply(this);
//In this case "this" is the window object which has the variable "b"
a.c.apply(this); // it'll print 2
You can do this:
var a = (function ()
{
return {
b: 1,
c: function ()
{
console.log(this.b);
}
}
})();
var decorator = function() { return a; };
var b = 2;
decorator.call(this).c(); // => 1
Basically it looks like you want to bind the IIFE, and not the object that it returns, to the outside scope, so that the nested returned object preserves the value of the interior b.

What's the benefit to export functions with self invoke functions than direct return

I've checked a lot of codes and I've saw a lot of people doing
module.exports = (function(){
return {
functionA: function() {
}
},
functionB: function() {
}
};
})();
so, why not just do
module.exports = {
functionA: function() {
},
functionB: function() {
}
};
Thanks!
Your first example allows you to hide variables within its own closure scope that can be shared with your return object's methods. The For example, if you did the following...
var foo = (function(){
var x = 2;
return {
addToTwo: function(y){
return x + y;
},
subtractFromTwo: function(y){
return x - y;
}
}
};
The above example shows that the x variable is protected and shared between addToTwo and subtractFromTwo. The second example only will allow you to make x as part of the object without the same protection.
module.exports = {
x: 3,
functionA: function() {
return this.x;
},
};
x can be altered in this example.
Those are exactly the same. It's a stylistic decision.
According to the Node.js docs:
Variables local to the module will be private, as though the module was wrapped in a function.
You could also do it this way:
module.exports.functionA = function() {
};
module.exports.functionB = function() {
};
Or:
// either method for creating a function works
function functionA () {}
var functionB = function () {}
module.exports = {
functionA : functionA,
functionB : functionB
};
One of the greatest advantages of directly invoked functions is the use of closures which cannot be obtianed in a separate manner, so literally they are not the same.

How to handle this to point to the upper most enclosing fn?

Imagine I have a fn like this:
var test = (function() {
var self = this;
var a = function() { (function() { self.b() })() }
var b = function() { console.log("hello") }
return { a:a,b:b }
})();
test a function calls the b function inside an another function. However I retained the this as self, still I'm getting issue:
test.a()
Uncaught TypeError: self.b is not a function(anonymous function) # VM246:4a # VM246:4(anonymous function) # VM247:2InjectedScript._evaluateOn # (program):883InjectedScript._evaluateAndWrap # (program):816InjectedScript.evaluate # (program):682
Where I'm making mistake? Why the self isn't retaining the this?
How to solve this issue?
Note
Changing the function to this:
var a = function() { (function() { b() })() }
this works. However I don't want to this way, because, imagine now I'm testing the function a calls function b. Now I want to spy b, if I do :
var spyb = sandbox.spy(test,"b")
and call:
test.a()
in the test code if I try to do the assertion:
assert(b.calledOnce)
this fails, as spy lib couldn't able to figure out test b fn is called.
So kindly help me to get the self way.
this within the anonymous function you use to build test is either undefined (in strict mode) or the global object (in loose mode); neither is what you want.
You don't need an object reference at all to call b from a:
var test = (function() {
var a = function() { (function() { b() })() }
// No need for an object -----------^
var b = function() { console.log("hello") }
return { a:a,b:b }
})();
Since a is a closure over the context of the call to the anonymous function, it has an enduring reference to b (as b does to a).
But if you want to use one, you could do this:
var test = (function() {
var obj = {
a: function() { (function() { obj.b() })() },
b: function() { console.log("hello") }
};
return obj;
})();
when you return
{a:a,b:b,c:self}
you would see 'self == window' is true, so the self is point to window.
but declare variables 'b' in function use 'var' , the scope of 'b' is in the function , not the window , so 'self' cannot reach the variables 'b'.
the correct is :
var test = function() {
var self = this;
self.a = function() { (function() { self.b() })() }
self.b = function() { console.log("hello") }
return { a:self.a,b:self.b }
};
var q = new test();
q.a(); //hello

How to call function A from function B within the same namespace?

Let's say I have the namespace,
var Namespace = {
A : function() {
alert('Hello!');
},
B : function() {
// Call A() from here, do other stuff
}
}
In this namespace, I intend for A to be a helper function to B. That is to say, A() will never be called outside the namespace. It will only be called by the functions within the namespace.
What's the best way to address the issue of a local/helper function within a namespace? The way I see it there are two possibilities:
// Method #1
var Namespace = {
A: function() {
alert('Method #1');
},
B : function() {
Namespace.A();
}
}
Namespace.B();
// Method #2
function Namespace2() {
var A = function() {
alert('Method #2');
};
this.B = function() {
A();
}
}
var ns2 = new Namespace2();
ns2.B();
In the first method, it is ugly and awkard to type Namespace.A() (repeatedly) in every function within the namespace. This leads me to prefer Method #2. But I was curious what was the best practice here.
I recommend placing the "namespace" inside a function scope. Everything not explicitly public will be naturally private:
var Namespace = (function() {
var self = {};
// Private
var A = function() {
...
};
// Public
self.B = function() {
A();
}
return self;
}());
Namespace.B(); // Works
Namespace.A(); // Doesn't work
You can call it using this statement
this.A();
Well you can event use a third option where the Namespace is created in it's own scope:
var Namespace = (function(){
var A = function() {
alert('scoped method');
};
function Namespace() {
var A1 = function() {
alert('Namespace "private" method');
};
Namespace.prototype.B1 = function(){
A(); //will run
A1(); //will run with no errors
};
};
Namespace.prototype.B = function(){
A(); //will run
A1(); //ERROR!
};
return Namespace;
})();
If you only intend to use A inside B, why not define it inside B?
var Namespace = {
B: function() {
var A = function() {
...
}
A();
}
};
Namespace.B();
var Namespace = {
A : function() {
alert('Hello!');
},
B : function() {
Namespace.A();
},
}
note the Semi-colon at the end

Objects literal and 'this' in submodule pattern

Im working in a sub-module pattern code. Want to create sub-modules with objects literals, the problem is this for the objects inside the sub-module is MODULE and not my object literal. Any idea?
var MODULE.sub = (function () {
var myObject = {
key: value,
method: function () {
this.key // this = MODULE and not MyObject... :(
}
};
return myObject.method;
}(MODULE));
This works for me:
var MODULE = MODULE || {};
MODULE.sub = (function () {
return {
myObject : {
key : 10,
method : function() {
console.log(this.key);
}
}
};
})();
Then call it:
MODULE.sub.myObject.method();
You were only returning the method and not the key so "this" would be undefined. You could keep it private if you want like this and pass key in as a var:
var MODULE = MODULE || {};
MODULE.sub = (function () {
var key = 10,
return {
myObject : {
method : function() {
console.log(key);
}
}
};
})();
Solved... just return a function in MODULE.sub calling the public method. I don't know if is the best approach
var MODULE.sub = (function () {
var myObject = {
key: value,
method: function () {
this.key // this = myObject :)
}
};
return function () {
myObject.method();
}
}(MODULE));
The this keywords value depends on how the function is called. So if you assign that function to MODULE.sub, and then invoke it as MODULE.sub(…), then this will point to the MODULE of course. If you had invoked it as myObject.method(…), then this would point to that object.
So you either should expose the whole myObject (like in #BingeBoys answer), or do not export that function and expect it to be a method of myObject. Instead, you could use a bound one:
return myObject.method.bind(myObject);
or the explicit equivalent of that
return function() {
return myObject.method();
};
or you would not put the function as method on that object at all:
…
var myObject = {
key: value,
};
return function() {
myObject.key // no `this` here
…
};
…

Categories